am affecd77: Cleanup CTS core failing tests.

Merge commit 'affecd7714e14fabff011ad61d436df3698bf7eb' into eclair

* commit 'affecd7714e14fabff011ad61d436df3698bf7eb':
  Cleanup CTS core failing tests.
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..28b19f6 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>
@@ -235,6 +236,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..0a6ce5c
--- /dev/null
+++ b/docs/heap-profiling.html
@@ -0,0 +1,164 @@
+<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>"Cupcake" release (1.5)</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.
+
+
+<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..690c213
--- /dev/null
+++ b/docs/hello-world.html
@@ -0,0 +1,169 @@
+<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>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..881f534 100644
--- a/docs/jni-tips.html
+++ b/docs/jni-tips.html
@@ -162,6 +162,12 @@
 <code>DeleteGlobalRef</code>.
 </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>
 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
@@ -201,9 +207,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>
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..84d513c 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 shipped with Android 1.0/1.5), 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/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..d6e8339 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,69 @@
 
         private ZipEntry zipEntry;
 
-        private JarVerifier verifier;
-
         private JarVerifier.VerifierEntry entry;
 
-        private MessageDigest digest;
-
-        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 (count > 0) {
+                int r = super.read();
                 if (r != -1) {
-                    digest.update((byte) r);
+                    entry.write(r);
                     count--;
+                } else {
+                    count = 0;
                 }
-                if (r == -1 || count <= 0) {
-                    JarVerifier.VerifierEntry temp = entry;
-                    entry = null;
-                    verifier.verifySignatures(temp, zipEntry);
+                if (count == 0) {
+                    entry.verify();
                 }
+                return r;
+            } else {
+                return -1;
             }
-            return r;
         }
 
         @Override
         public int read(byte[] buf, int off, int nbytes) throws IOException {
-            int r = super.read(buf, off, nbytes);
-            if (entry != null) {
+            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) {
+                    entry.verify();
                 }
+                return r;
+            } else {
+                return -1;
             }
-            return r;
         }
 
+        // BEGIN android-added
+        @Override
+        public int available() throws IOException {
+            if (count > 0) {
+                return super.available();
+            } else {
+                return 0;
+            }
+        }
+        // END android-added
+
         @Override
         public long skip(long nbytes) throws IOException {
             long cnt = 0, rem = 0;
@@ -146,12 +148,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 +160,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 +178,7 @@
 
     /**
      * Create a new {@code JarFile} using the contents of file.
-     * 
+     *
      * @param file
      *            the JAR file as {@link File}.
      * @param verify
@@ -188,7 +188,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 +200,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 +214,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 +233,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 +256,7 @@
 
             public JarEntry nextElement() {
                 JarEntry je = new JarEntry(ze.nextElement());
-                je.parentJar = jf;                
+                je.parentJar = jf;
                 return je;
             }
         }
@@ -270,11 +266,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 +297,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 +352,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 +377,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 +392,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 +408,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 +433,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 +464,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..8145fa1 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
@@ -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
@@ -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..bb84f5b 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,12 +145,23 @@
         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){
+        if (eof) {
             return -1;
         }
         // avoid int overflow, check null buffer
@@ -164,17 +173,15 @@
             } 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)
+                // 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
+                readFully(b, copySize, trailerSize - copySize);
+
                 if (getLong(b, 0) != crc.getValue()) {
                     throw new IOException(Messages.getString("archive.20")); //$NON-NLS-1$
                 }
@@ -186,12 +193,6 @@
         }
         throw new ArrayIndexOutOfBoundsException();
     }
-    
-    @Override
-    public void close() throws IOException {
-        eos = true;
-        super.close();
-    }
 
     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..cb1ce68 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,65 @@
  * 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;
+
+    // Fill in the JNI id caches
+    private static native void oneTimeInitialization();
+
+    private boolean finished; // Set by the inflateImpl native
+
     private boolean gotFirstByte = false;
+
+    int inLength;
+
+    int inRead;
+
+    private boolean needsDictionary; // Set by the inflateImpl native
+
     private boolean pass_magic_number_check = true;
-    
+
+    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);
+    }
+
+    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 +111,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 +122,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 +136,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 +178,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 +195,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 +211,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 +226,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,7 +249,7 @@
             if (streamHandle == -1) {
                 throw new IllegalStateException();
             }
-            
+
             if (!pass_magic_number_check) {
                 throw new DataFormatException();
             }
@@ -213,7 +257,7 @@
             if (needsInput()) {
                 return 0;
             }
-            
+
             boolean neededDict = needsDictionary;
             needsDictionary = false;
             int result = inflateImpl(buf, off, nbytes, streamHandle);
@@ -229,41 +273,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 +289,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 +301,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 +318,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 +330,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 +342,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 +362,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 +376,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 +384,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) {
@@ -394,10 +409,9 @@
         //        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;
+        if (!gotFirstByte && nbytes > 0) {
+            pass_magic_number_check = (buf[off] == MAGIC_NUMBER || nbytes > 1);
+            gotFirstByte = true;
         }
     }
 
@@ -407,14 +421,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 +439,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 +446,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..1fd3602 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,31 +30,24 @@
  * (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;
 
@@ -74,10 +66,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 +77,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 +90,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 +118,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 +135,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 +145,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 {
@@ -197,7 +184,7 @@
                     if (len == -1) {
                         throw new EOFException();
                     }
-                    throw (IOException)(new IOException().initCause(e));
+                    throw (IOException) (new IOException().initCause(e));
                 }
                 if (result > 0) {
                     return result;
@@ -208,20 +195,18 @@
                     return -1;
                 } else if (len == -1) {
                     throw new EOFException();
-                // If result == 0, fill() and try again
+                    // If result == 0, fill() and try again
                 }
             } while (true);
         }
         throw new ArrayIndexOutOfBoundsException();
     }
 
-    
     /**
      * 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,17 +231,21 @@
 
     /**
      * 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,
@@ -275,11 +264,10 @@
 
     /**
      * Returns whether data can be read from this stream.
-     * 
+     *
      * @return 0 if this stream has been closed, 1 otherwise.
      * @throws IOException
      *             If an error occurs.
-     * @since Android 1.0
      */
     @Override
     public int available() throws IOException {
@@ -295,10 +283,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 +296,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 +313,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..1a35b1c 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
@@ -173,13 +165,12 @@
 
     /**
      * Reads the next entry from this {@code ZipInputStream}.
-     * 
+     *
      * @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.
      * @see ZipEntry
-     * @since Android 1.0
      */
     public ZipEntry getNextEntry() throws IOException {
         if (currentEntry != null) {
@@ -274,6 +265,18 @@
 
     /* 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
@@ -340,13 +343,12 @@
 
     /**
      * 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 +366,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 {
@@ -389,11 +390,10 @@
 
     /**
      * 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..96321a4 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,13 +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.AndroidOnly;
 import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargets;
 import dalvik.annotation.TestLevel;
 import dalvik.annotation.TestTargetNew;
 
@@ -73,13 +71,17 @@
     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 integrateJar = "Integrate.jar";
+
     private final String entryName = "foo/bar/A.class";
 
     private final String entryName3 = "coucou/FileAccess.class";
 
+    private final String integrateJarEntry = "Test.class";
+
     private File resources;
 
     // custom security manager
@@ -102,7 +104,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 +302,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 +339,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 +359,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 +380,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 +461,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 +645,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 +686,7 @@
         } catch (Exception e) {
             fail("Exception during test 4: " + e);
         }
-        
+
         try {
             JarFile jar = new JarFile(signedFile);
             JarEntry entry = new JarEntry(entryName3);
@@ -682,7 +708,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 +758,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 +837,6 @@
         Enumeration<JarEntry> entries = jarFile.entries();
         int count = 0;
         while (entries.hasMoreElements()) {
-
             ZipEntry zipEntry = entries.nextElement();
             jarFile.getInputStream(zipEntry);
             count++;
@@ -818,7 +873,7 @@
             while (in.available() > 0) {
                 in.read(buffer);
             }
-            fail("should throw Security Exception");
+            fail("SecurityException expected");
         } catch (SecurityException e) {
             // desired
         }
@@ -827,7 +882,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 +901,7 @@
             ZipEntry zipEntry = entries.nextElement();
             try {
                 jarFile.getInputStream(zipEntry);
-                fail("should throw Security Exception");
+                fail("SecurityException expected");
             } catch (SecurityException e) {
                 // desired
             }
@@ -927,4 +982,83 @@
 
         // 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
+        }
+    }
 }
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/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/InflaterTest.java b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/InflaterTest.java
index 8b89180..6039c5b 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(
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..c9e7bb8 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
@@ -67,7 +67,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 +145,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 +260,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 +270,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 +450,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/ZipOutputStreamTest.java b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/ZipOutputStreamTest.java
index 9a5f63a..8ca551d 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
@@ -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 fa9dfe8..41f3a6d 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
@@ -155,8 +153,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() {
@@ -167,9 +165,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() {
@@ -185,12 +183,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/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/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/SamplingProfiler.java b/libcore/dalvik/src/main/java/dalvik/system/SamplingProfiler.java
new file mode 100644
index 0000000..694df38
--- /dev/null
+++ b/libcore/dalvik/src/main/java/dalvik/system/SamplingProfiler.java
@@ -0,0 +1,229 @@
+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());
+
+    /** Pointer to native state. */
+    int pointer = 0;
+
+    /** The thread that collects samples. */
+    Thread samplingThread;
+
+    /** Whether or not the profiler is running. */
+    boolean running = false;
+    int delayPerThread; // ms
+
+    /** Number of samples taken. */
+    int sampleCount = 0;
+
+    /** Total time spent collecting samples. */
+    long totalSampleTime = 0;
+
+    private SamplingProfiler() {}
+
+    /**
+     * Returns true if the profiler is running.
+     */
+    public boolean isRunning() {
+        return running;
+    }
+
+    /**
+     * Starts collecting samples.
+     *
+     * @param threadsPerSecond number of threads to sample per second
+     */
+    public synchronized void start(int threadsPerSecond) {
+        if (threadsPerSecond < 1) {
+            throw new IllegalArgumentException("threadsPerSecond < 1");
+        }
+        if (!running) {
+            logger.info("Starting profiler.");
+            running = true;
+            if (samplingThread == null) {
+                // TODO: Priority?
+                samplingThread = new Thread(new Sampler());
+                samplingThread.setDaemon(true);
+                samplingThread.start();
+            } else {
+                notifyAll();
+            }
+        }
+        delayPerThread = 1000 / threadsPerSecond;
+    }
+
+    /**
+     * Stops sample collection.
+     */
+    public synchronized void stop() {
+        if (running) {
+            logger.info("Stopping profiler.");
+            running = false;
+        }
+    }
+
+    /**
+     * 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.
+     */
+    public synchronized byte[] snapshot() {
+        if (pointer == 0 || sampleCount == 0) {
+            return null;
+        }
+
+        int size = size(pointer);
+        int collisions = collisions(pointer);
+
+        long start = System.nanoTime();
+        byte[] bytes = snapshot(pointer);
+        long elapsed = System.nanoTime() - start;
+
+        logger.info("Grabbed snapshot in " + (elapsed / 1000) + "us."
+                + " Samples collected: " + sampleCount
+                + ", Average sample time (per thread): "
+                    + (((totalSampleTime / sampleCount) << 10) / 1000) + "us"
+                + ", Set size: " + size
+                + ", Collisions: " + collisions);
+        sampleCount = 0;
+        totalSampleTime = 0;
+
+        return bytes;
+    }
+
+    /**
+     * 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.
+     */
+    public synchronized void setEventThread(Thread eventThread) {
+        if (pointer == 0) {
+            pointer = allocate();
+        }
+        setEventThread(pointer, eventThread);
+    }
+
+    /** Collects some data. Returns number of threads sampled. */
+    private static native int sample(int pointer);
+
+    /** Allocates native state. */
+    private static native int allocate();
+
+    /** 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) {
+                int threadsSampled;
+                synchronized (SamplingProfiler.this) {
+                    if (!running) {
+                        logger.info("Stopped profiler.");
+                        while (!running) {
+                            try {
+                                SamplingProfiler.this.wait();
+                            } catch (InterruptedException e) { /* ignore */ }
+                        }
+                        firstSample = true;
+                    }
+
+                    if (pointer == 0) {
+                        pointer = allocate();
+                    }
+
+                    if (firstSample) {
+                        logger.info("Started profiler.");
+                        firstSample = false;
+                    }
+
+                    long start = System.nanoTime();
+                    threadsSampled = sample(pointer);
+                    long elapsed = System.nanoTime() - start;
+
+                    sampleCount += threadsSampled;
+                    totalSampleTime += elapsed >> 10; // shift avoids overflow.
+                }
+
+                try {
+                    Thread.sleep(delayPerThread * threadsSampled);
+                } 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: ").append(in.readShort()).append('\n');
+        sb.append("      native: ").append(in.readShort()).append('\n');
+        sb.append("      suspended: ").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/VMDebug.java b/libcore/dalvik/src/main/java/dalvik/system/VMDebug.java
index efc25d6..bcc8b61 100644
--- a/libcore/dalvik/src/main/java/dalvik/system/VMDebug.java
+++ b/libcore/dalvik/src/main/java/dalvik/system/VMDebug.java
@@ -275,8 +275,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/VMStack.java b/libcore/dalvik/src/main/java/dalvik/system/VMStack.java
index 9330c68..365613e 100644
--- a/libcore/dalvik/src/main/java/dalvik/system/VMStack.java
+++ b/libcore/dalvik/src/main/java/dalvik/system/VMStack.java
@@ -40,6 +40,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/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..f2bd62d 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,6 +29,8 @@
 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;
 
@@ -4628,6 +4630,26 @@
         }
     }
 
+    /*
+     * test initHandler
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "",
+        method = "initHandler",
+        args = {}
+    )
+    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..6adf4db 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;
     }
 
     /*
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..484c258 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,10 +915,10 @@
      * 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() {
@@ -934,7 +936,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 +951,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 +971,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 +997,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 +1015,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 +1067,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 +1090,7 @@
      * holds. If no Runnable is set, does nothing.
      *
      * @see Thread#start
-     * 
+     *
      * @since Android 1.0
      */
     public void run() {
@@ -1073,7 +1111,7 @@
      *         checkPermission call.
      * @see java.lang.ClassLoader
      * @see #getContextClassLoader()
-     * 
+     *
      * @since Android 1.0
      */
     public void setContextClassLoader(ClassLoader cl) {
@@ -1088,13 +1126,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 +1156,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 +1197,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 +1220,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 +1229,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 +1256,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 +1274,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 +1292,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 +1301,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 +1314,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 +1338,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 +1359,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 +1388,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 +1409,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 +1422,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 +1436,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 +1448,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 +1459,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 +1482,7 @@
             parkState = ParkState.PREEMPTIVELY_UNPARKED;
             return;
         }
-        
+
         synchronized (vmt) {
             switch (parkState) {
                 case ParkState.PREEMPTIVELY_UNPARKED: {
@@ -1468,12 +1506,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 +1521,7 @@
             // Running threads should always have an associated vmThread.
             throw new AssertionError();
         }
-        
+
         synchronized (vmt) {
             switch (parkState) {
                 case ParkState.PREEMPTIVELY_UNPARKED: {
@@ -1491,8 +1529,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 +1545,7 @@
                          */
                         if (parkState == ParkState.PARKED) {
                             parkState = ParkState.UNPARKED;
-                        }                            
+                        }
                     }
                     break;
                 }
@@ -1515,7 +1553,7 @@
                     throw new AssertionError(
                             "shouldn't happen: attempt to repark");
                 }
-            }       
+            }
         }
     }
 
@@ -1523,7 +1561,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 +1571,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 +1592,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..7dc87ff 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,9 @@
                 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.
-                        Class<?> fieldType = field.getTypeInternal();
-                        // END android-added                        
+                        Class<?> fieldType = fieldDesc.getType();
                         Class<?> valueType = toSet.getClass();
                         if (!fieldType.isAssignableFrom(valueType)) {
                             throw new ClassCastException(Msg.getString(
@@ -1319,8 +1333,10 @@
                                                     + fieldName }));
                         }
                         try {
+                            // BEGIN android-changed
                             objSetField(obj, declaringClass, fieldName, field
                                     .getTypeString(), toSet);
+                            // END android-changed
                         } catch (NoSuchFieldError e) {
                             // Ignored
                         }
@@ -1332,14 +1348,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 +1363,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 +1371,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 +1380,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 +1393,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 +1407,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 +1422,7 @@
      * @throws NotActiveException
      *             If {@code defaultReadObject} is called from the wrong
      *             context.
-     * 
+     *
      * @see #defaultReadObject
      * @see #readObject()
      */
@@ -1449,7 +1462,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 +1496,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 +1517,7 @@
                 throw new RuntimeException(e.toString());
             }
         }
+
     }
 
     private void readObjectForClass(Object object, ObjectStreamClass classDesc)
@@ -1518,12 +1529,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 +1573,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 +1601,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 +1616,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 +1636,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 +1697,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 +1714,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 +1729,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 +1763,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 +1797,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 +1826,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 +1843,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 +1881,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 +1905,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 +1940,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 +1950,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 +1972,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 +2044,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 +2154,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 +2191,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 +2203,7 @@
         if (enableResolve) {
             result = resolveObject(result);
         }
-        int newHandle = nextHandle();
-        registerObjectRead(result, Integer.valueOf(newHandle), unshared);
+		registerObjectRead(result, nextHandle(), unshared);
 
         return result;
     }
@@ -2204,11 +2211,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 +2225,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 +2242,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 +2250,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 +2258,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 +2351,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 +2361,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 +2373,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 +2384,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 +2402,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 +2410,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 +2417,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 +2425,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 +2433,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 +2441,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 +2448,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 +2470,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 +2492,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 +2510,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 +2550,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 +2570,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 +2579,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 +2606,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 +2616,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 +2688,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 +2708,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 +2741,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..83987ec 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 {
 
@@ -36,29 +34,21 @@
 
     /**
      * The circular buffer through which data is passed.
-     * 
-     * @since Android 1.0
      */
     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 +61,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 +70,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 +84,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 +100,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 +119,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 +139,29 @@
      * 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$
         }
+
+        if (lastWriter != null && !lastWriter.isAlive() && (in < 0)) {
+            // KA030=Write end dead
+            throw new IOException(Msg.getString("KA030")); //$NON-NLS-1$
+        }
         /**
          * Set the last thread to be reading on this PipedInputStream. If
          * lastReader dies while someone is waiting to write an IOException of
@@ -180,16 +169,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);
@@ -219,8 +208,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 +252,20 @@
         }
 
         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$
         }
 
+        if (lastWriter != null && !lastWriter.isAlive() && (in < 0)) {
+            // KA030=Write end dead
+            throw new IOException(Msg.getString("KA030")); //$NON-NLS-1$
+        }
+
         /**
          * Set the last thread to be reading on this PipedInputStream. If
          * lastReader dies while someone is waiting to write an IOException of
@@ -278,16 +273,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);
@@ -342,8 +337,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
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..6b3b6cc 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,12 +72,11 @@
      * 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();
@@ -92,14 +88,13 @@
      * 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();
@@ -111,10 +106,9 @@
      * 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,10 +219,9 @@
     /**
      * 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()) {
@@ -257,10 +244,9 @@
 
     /**
      * 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 {
@@ -630,13 +612,14 @@
      * 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);
@@ -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..23efa5e 100644
--- a/libcore/luni/src/main/java/java/net/Inet4Address.java
+++ b/libcore/luni/src/main/java/java/net/Inet4Address.java
@@ -28,8 +28,6 @@
  * 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 {
 
@@ -50,7 +48,6 @@
      * 
      * @return {@code true} if this instance represents a multicast address,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isMulticastAddress() {
@@ -63,7 +60,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 +77,6 @@
      * 
      * @return {@code true} if this instance represents a lookback address,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isLoopbackAddress() {
@@ -95,11 +90,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 +108,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 +126,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 +164,6 @@
      * addresses.
      * 
      * @return {@code false} for all IPv4 addresses.
-     * @since Android 1.0
      */
     @Override
     public boolean isMCNodeLocal() {
@@ -188,7 +177,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 +190,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 +204,6 @@
      * 
      * @return {@code true} if this instance represents a organization-local
      *         address, {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isMCOrgLocal() {
@@ -229,7 +215,6 @@
      * Returns a textual representation of this IP address.
      * 
      * @return the textual representation of this host address.
-     * @since Android 1.0
      */
     @Override
     public String getHostAddress() {
@@ -247,7 +232,6 @@
      * Gets the hashcode of the represented IP address.
      * 
      * @return the appropriate hashcode value.
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -262,7 +246,6 @@
      * @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) {
diff --git a/libcore/luni/src/main/java/java/net/Inet6Address.java b/libcore/luni/src/main/java/java/net/Inet6Address.java
index 4c10faa..0569829 100644
--- a/libcore/luni/src/main/java/java/net/Inet6Address.java
+++ b/libcore/luni/src/main/java/java/net/Inet6Address.java
@@ -28,8 +28,6 @@
 
 /**
  * This class represents a 128 bit long IPv6 address.
- * 
- * @since Android 1.0
  */
 public final class Inet6Address extends InetAddress {
 
@@ -80,7 +78,6 @@
      *            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) {
         hostName = name;
@@ -104,7 +101,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 +131,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 +172,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 +199,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 +214,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 +227,6 @@
      * 
      * @return {@code true} if this instance represents a wildcard address,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isAnyLocalAddress() {
@@ -251,7 +244,6 @@
      * 
      * @return {@code true} if this instance represents the loopback address,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isLoopbackAddress() {
@@ -277,7 +269,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 +283,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 +297,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 +312,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 +327,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 +342,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 +357,6 @@
      * 
      * @return {@code true} if this instance represents a org-local multicast
      *         address, {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isMCOrgLocal() {
@@ -384,7 +369,6 @@
      * 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() {
@@ -397,7 +381,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 +394,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) {
@@ -424,7 +406,6 @@
      * Gets the hashcode of the represented IP address.
      * 
      * @return the appropriate hashcode value.
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -441,7 +422,6 @@
      * @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) {
@@ -455,7 +435,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 +485,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..eec153f 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,8 +43,6 @@
  * 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 {
 
@@ -86,7 +86,7 @@
     // BEGIN android-removed
     // // Fill in the JNI id caches
     // private static native void oneTimeInitialization(boolean supportsIPv6);
-    // 
+    //
     // static {
     //     oneTimeInitialization(true);
     // }
@@ -102,7 +102,7 @@
     /**
      * Constructs an {@code InetAddress}, representing the {@code address} and
      * {@code hostName}.
-     * 
+     *
      * @param address
      *            the network address.
      */
@@ -114,7 +114,7 @@
     /**
      * Constructs an {@code InetAddress}, representing the {@code address} and
      * {@code hostName}.
-     * 
+     *
      * @param address
      *            the network address.
      */
@@ -125,38 +125,19 @@
     }
 
     // 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;
+    // CacheElement cacheElement() {
+    //     return new CacheElement();
     // }
-    // 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) {
@@ -185,120 +166,125 @@
      * 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, LOOPBACK };
+            } else {
+                return new InetAddress[] { LOOPBACK, Inet6Address.LOOPBACK };
+            }
+        }
+
+        // Special-case "0" for legacy IPv4 applications.
+        if (host.equals("0")) { //$NON-NLS-1$
+            return new InetAddress[] { InetAddress.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
         if (hBytes.length == 4) {
             return (new InetAddress[] { new Inet4Address(hBytes) });
         } else if (hBytes.length == 16) {
             return (new InetAddress[] { new Inet6Address(hBytes) });
         }
-        // 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,45 +292,22 @@
      * 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];
     }
 
     /**
      * 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
      */
     public String getHostAddress() {
         return inetNtoaImpl(bytesToInt(ipaddress, 0));
@@ -354,9 +317,8 @@
      * 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 {
@@ -395,9 +357,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;
@@ -429,14 +390,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();
@@ -448,14 +405,13 @@
         } catch (SecurityException e) {
             return InetAddress.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() {
@@ -464,16 +420,21 @@
 
     /**
      * Returns whether this address is an IP multicast address or not.
-     * 
+     *
      * @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;
     }
 
-    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 +451,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 +509,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
@@ -587,12 +556,12 @@
         // 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);
@@ -612,35 +581,30 @@
         int b = (hipAddr >> 16) & 0xFF;
         int c = (hipAddr >>  8) & 0xFF;
         int d = (hipAddr      ) & 0xFF;
-        
+
         return "" + a + "." + b + "." + c + "." + d;
     }
     // END android-changed
 
+    // 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
@@ -657,7 +621,7 @@
             return InetAddress.LOOPBACK.getHostAddress();
         }
         if (isHostName(host)) {
-            return lookupHostByName(host).getHostAddress();
+            return lookupHostByName(host)[0].getHostAddress();
         }
         return host;
     }
@@ -665,38 +629,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 +673,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,7 +728,6 @@
             }
         }
     }
-    // END android-changed
 
     /**
      * Returns true if the string is a host name, false if it is an IP Address.
@@ -778,10 +741,9 @@
      * 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 +755,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 +771,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 +788,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 +806,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 +823,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 +840,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 +858,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 +872,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 +884,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 +894,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 +903,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 +918,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 +1011,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 +1060,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 +1073,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,18 +1099,15 @@
      * 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 {
@@ -1187,7 +1122,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
@@ -1204,10 +1139,7 @@
             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) {
@@ -1224,6 +1156,8 @@
             copy_address = ipAddress.clone();
             return new Inet6Address(copy_address, scope_id);
         }
+
+        // K0339=Invalid IP Address is neither 4 or 16 bytes
         throw new UnknownHostException(Msg.getString("K0339")); //$NON-NLS-1$
     }
 
@@ -1251,15 +1185,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 +1199,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 +1214,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
diff --git a/libcore/luni/src/main/java/java/net/InetSocketAddress.java b/libcore/luni/src/main/java/java/net/InetSocketAddress.java
index 6901053..13c10f2 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 {
 
@@ -40,10 +38,9 @@
      * 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.
-     * 
+     *
      * @param port
      *            the specified port number to which this socket is bound.
-     * @since Android 1.0
      */
     public InetSocketAddress(int port) {
         this((InetAddress) null, port);
@@ -54,12 +51,11 @@
      * {@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}.
-     * 
+     *
      * @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) {
@@ -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..0b1c99b 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);
@@ -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);
@@ -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 {
@@ -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..e166db4 100644
--- a/libcore/luni/src/main/java/java/net/NegCacheElement.java
+++ b/libcore/luni/src/main/java/java/net/NegCacheElement.java
@@ -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;
-    
+
     /**
      * Constructor used to set the hostname for the entry for which the lookup
      * failed.
-     * 
+     *
      * @param hostName
      *            name of the host for which the lookup failed.
      */
     NegCacheElement(String hostName) {
         this.hostName = hostName;
     }
-    // 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..e66d3f3 100644
--- a/libcore/luni/src/main/java/java/net/NegativeCache.java
+++ b/libcore/luni/src/main/java/java/net/NegativeCache.java
@@ -25,16 +25,13 @@
 /**
  * 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
@@ -42,13 +39,17 @@
 
     // the loading for the cache
     private static final float LOADING = 0.75F;
-    // END android-changed
 
     /**
-     * Returns the hostname for the cache element.
-     * 
-     * @return hostName name of the host for which the lookup failed.
-     * @since Android 1.0
+     * Constructs a negative cache for name lookups.
+     *
+     * @param initialCapacity
+     *            the initial size of the cache.
+     * @param loadFactor
+     *            the load factor of the backing map.
+     * @param accessOrder
+     *            if {@code true} indicates that traversal order should begin
+     *            with most recently accessed element.
      */
     NegativeCache(int initialCapacity, float loadFactor, boolean accessOrder) {
         super(initialCapacity, loadFactor, accessOrder);
@@ -59,10 +60,9 @@
      * 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) {
@@ -72,17 +72,13 @@
     /**
      * 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));
     }
@@ -90,17 +86,13 @@
     /**
      * 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) {
@@ -130,10 +122,7 @@
             }
         }
         if (element != null) {
-            // BEGIN android-changed
-            // Copied from a newer version of harmony
             return element.hostName;
-            // END android-changed
         }
         return null;
     }
@@ -148,13 +137,9 @@
     // END android-added
 
     /**
-     * This method checks whether the cache was already created and if not
-     * creates it.
+     * This method checks if we have created the cache 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
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..99fad3f 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,12 +77,11 @@
      * 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);
@@ -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,7 +100,6 @@
      *            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);
@@ -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,14 +120,13 @@
      *            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();
+                : new PlainServerSocketImpl();
         InetAddress addr = localAddr == null ? InetAddress.ANY : localAddr;
 
         synchronized (this) {
@@ -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);
@@ -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..71a1bf2 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,10 +473,9 @@
 
     /**
      * 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()) {
@@ -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
@@ -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);
@@ -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 {
@@ -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..999063d 100644
--- a/libcore/luni/src/main/java/java/util/HashMap.java
+++ b/libcore/luni/src/main/java/java/util/HashMap.java
@@ -25,25 +25,46 @@
 /**
  * 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
  */
 public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>,
         Cloneable, Serializable {
+
     private static final long serialVersionUID = 362498820763181265L;
 
+    /*
+     * Actual count of entries
+     */
     transient int elementCount;
 
+    /*
+     * The internal data structure to hold Entries
+     */
     transient Entry<K, V>[] elementData;
 
-    final float loadFactor;
-
-    int threshold;
-
+    /*
+     * modification count, to keep track of structural modifications between the
+     * HashMap and the iterator
+     */
     transient int modCount = 0;
 
+    /*
+     * default size that an HashMap created using the default constructor would
+     * have.
+     */
     private static final int DEFAULT_SIZE = 16;
 
+    /*
+     * maximum ratio of (stored elements)/(storage size) which does not lead to
+     * rehash
+     */
+    final float loadFactor;
+
+    /*
+     * maximum number of elements that can be put in this map before having to
+     * rehash
+     */
+    int threshold;
+
     static class Entry<K, V> extends MapEntry<K, V> {
         final int origKeyHash;
 
@@ -56,7 +77,7 @@
 
         Entry(K theKey, V theValue) {
             super(theKey, theValue);
-            origKeyHash = (theKey == null ? 0 : theKey.hashCode());
+            origKeyHash = (theKey == null ? 0 : computeHashCode(theKey));
         }
 
         @Override
@@ -70,33 +91,27 @@
         }
     }
 
-    static class HashMapIterator<E, KT, VT> implements Iterator<E> {
+    private static class AbstractMapIterator<K, V>  {
         private int position = 0;
-
         int expectedModCount;
+        Entry<K, V> futureEntry;
+        Entry<K, V> currentEntry;
+        Entry<K, V> prevEntry;
 
-        final MapEntry.Type<E, KT, VT> type;
+        final HashMap<K, V> associatedMap;
 
-        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) {
+        AbstractMapIterator(HashMap<K, V> hm) {
             associatedMap = hm;
-            type = value;
             expectedModCount = hm.modCount;
+            futureEntry = null;
         }
 
         public boolean hasNext() {
-            if (entry != null) {
+            if (futureEntry != null) {
                 return true;
             }
             // BEGIN android-changed
-            Entry<KT, VT>[] elementData = associatedMap.elementData;
+            Entry<K, V>[] elementData = associatedMap.elementData;
             int length = elementData.length;
             int newPosition = position;
             boolean result = false;
@@ -115,58 +130,88 @@
             // END android-changed
         }
 
-        void checkConcurrentMod() throws ConcurrentModificationException {
+        final void checkConcurrentMod() throws ConcurrentModificationException {
             if (expectedModCount != associatedMap.modCount) {
                 throw new ConcurrentModificationException();
             }
         }
 
-        public E next() {
+        final void makeNext() {
             // BEGIN android-changed
             // inline checkConcurrentMod()
             if (expectedModCount != associatedMap.modCount) {
                 throw new ConcurrentModificationException();
             }
+            // END android-changed
             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;
+            if (futureEntry == null) {
+                currentEntry = associatedMap.elementData[position++];
+                futureEntry = currentEntry.next;
+                prevEntry = null;
             } else {
-                if (lastEntry.next != _entry) {
-                    lastEntry = lastEntry.next;
+                if(currentEntry!=null){
+                    prevEntry = currentEntry;
                 }
-                result = _entry;
-                entry = _entry.next;
+                currentEntry = futureEntry;
+                futureEntry = futureEntry.next;
             }
-            canRemove = true;
-            return type.get(result);
-            // END android-changed
         }
 
-        public void remove() {
+        public final void remove() {
             checkConcurrentMod();
-            if (!canRemove) {
+            if (currentEntry==null) {
                 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;
+            if(prevEntry==null){
+                int index = currentEntry.origKeyHash & (associatedMap.elementData.length - 1);
+                associatedMap.elementData[index] = associatedMap.elementData[index].next;
             } else {
-                lastEntry.next = entry;
+                prevEntry.next = currentEntry.next;
             }
-            associatedMap.elementCount--;
+            currentEntry = null;
             expectedModCount++;
+            associatedMap.modCount++;
+            associatedMap.elementCount--;
+
+        }
+    }
+
+
+    private static class EntryIterator <K, V> extends AbstractMapIterator<K, V> implements Iterator<Map.Entry<K, V>> {
+
+        EntryIterator (HashMap<K, V> map) {
+            super(map);
+        }
+
+        public Map.Entry<K, V> next() {
+            makeNext();
+            return currentEntry;
+        }
+    }
+
+    private static class KeyIterator <K, V> extends AbstractMapIterator<K, V> implements Iterator<K> {
+
+        KeyIterator (HashMap<K, V> map) {
+            super(map);
+        }
+
+        public K next() {
+            makeNext();
+            return currentEntry.key;
+        }
+    }
+
+    private static class ValueIterator <K, V> extends AbstractMapIterator<K, V> implements Iterator<V> {
+
+        ValueIterator (HashMap<K, V> map) {
+            super(map);
+        }
+
+        public V next() {
+            makeNext();
+            return currentEntry.value;
         }
     }
 
@@ -193,9 +238,13 @@
 
         @Override
         public boolean remove(Object object) {
-            if (contains(object)) {
-                associatedMap.remove(((Map.Entry<?, ?>) object).getKey());
-                return true;
+            if (object instanceof Map.Entry) {
+                Map.Entry<?, ?> oEntry = (Map.Entry<?, ?>) object;
+                Entry<KT,VT> entry = associatedMap.getEntry(oEntry.getKey());
+                if(valuesEq(entry, oEntry)) {
+                    associatedMap.removeEntry(entry);
+                    return true;
+                }
             }
             return false;
         }
@@ -203,31 +252,32 @@
         @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);
+                Map.Entry<?, ?> oEntry = (Map.Entry<?, ?>) object;
+                Entry<KT, VT> entry = associatedMap.getEntry(oEntry.getKey());
+                return valuesEq(entry, oEntry);
             }
             return false;
         }
 
+        private static boolean valuesEq(Entry entry, Map.Entry<?, ?> oEntry) {
+            return (entry != null) &&
+                                   ((entry.value == null) ?
+                                    (oEntry.getValue() == null) :
+                                    (areEqualValues(entry.value, oEntry.getValue())));
+        }
+
         @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);
+            return new EntryIterator<KT,VT> (associatedMap);
         }
     }
 
+    /**
+     * Create a new element array
+     *
+     * @param s
+     * @return Reference to the element array
+     */
     @SuppressWarnings("unchecked")
     Entry<K, V>[] newElementArray(int s) {
         return new Entry[s];
@@ -235,8 +285,6 @@
 
     /**
      * Constructs a new empty {@code HashMap} instance.
-     * 
-     * @since Android 1.0
      */
     public HashMap() {
         this(DEFAULT_SIZE);
@@ -244,28 +292,47 @@
 
     /**
      * 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();
+        this(capacity, 0.75f);  // default load factor of 0.75
         }
+
+    /**
+     * Calculates the capacity of storage required for storing given number of
+     * elements
+     *
+     * @param x
+     *            number of elements
+     * @return storage size
+     */
+    private static final int calculateCapacity(int x) {
+        if(x >= 1 << 30){
+            return 1 << 30;
+        }
+        if(x == 0){
+            return 16;
+        }
+        // BEGIN android-note
+        // this may be better optimized as Integer.highestOneBit(x)
+        // END android-note
+        x = x -1;
+        x |= x >> 1;
+        x |= x >> 2;
+        x |= x >> 4;
+        x |= x >> 8;
+        x |= x >> 16;
+        return x + 1;
     }
 
     /**
      * Constructs a new {@code HashMap} instance with the specified capacity and
      * load factor.
-     * 
+     *
      * @param capacity
      *            the initial capacity of this hash map.
      * @param loadFactor
@@ -273,14 +340,14 @@
      * @throws IllegalArgumentException
      *                when the capacity is less than zero or the load factor is
      *                less or equal to zero.
-     * @since Android 1.0
      */
     public HashMap(int capacity, float loadFactor) {
         if (capacity >= 0 && loadFactor > 0) {
+            capacity = calculateCapacity(capacity);
             elementCount = 0;
-            elementData = newElementArray(capacity == 0 ? 1 : capacity);
+            elementData = newElementArray(capacity);
             this.loadFactor = loadFactor;
-            computeMaxSize();
+            computeThreshold();
         } else {
             throw new IllegalArgumentException();
         }
@@ -289,29 +356,29 @@
     /**
      * 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);
+        this(calculateCapacity(map.size()));
         putAllImpl(map);
     }
 
-    // BEGIN android-changed
     /**
      * Removes all mappings from this hash map, leaving it empty.
-     * 
+     *
      * @see #isEmpty
      * @see #size
-     * @since Android 1.0
      */
     @Override
     public void clear() {
+        // BEGIN android-changed
         internalClear();
+        // END android-changed
     }
 
+    // BEGIN android-added
     void internalClear() {
         if (elementCount > 0) {
             elementCount = 0;
@@ -319,89 +386,71 @@
             modCount++;
         }
     }
-    // END android-changed
+    // END android-added
 
     /**
      * Returns a shallow copy of this map.
-     * 
+     *
      * @return a shallow copy of this map.
-     * @since Android 1.0
      */
     @Override
     @SuppressWarnings("unchecked")
     public Object clone() {
         try {
-            // BEGIN android-changed
-            // copied from newer version of harmony
             HashMap<K, V> map = (HashMap<K, V>) super.clone();
+            map.elementCount = 0;
             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
-            }
+            map.putAll(this);
+
             return map;
         } catch (CloneNotSupportedException e) {
             return null;
         }
     }
 
-    private void computeMaxSize() {
+    /**
+     * Computes the threshold for rehashing
+     */
+    private void computeThreshold() {
         threshold = (int) (elementData.length * loadFactor);
     }
 
     /**
      * 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;
-        if (key == null) {
-            m = findNullKeyEntry();
-        } else {
-            int hash = key.hashCode();
-            int index = (hash & 0x7FFFFFFF) % elementData.length;
-            m = findNonNullKeyEntry(key, index, hash);
-        }
+        Entry<K, V> m = getEntry(key);
         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;) {
+            for (int i = 0; i < elementData.length; i++) {
                 Entry<K, V> entry = elementData[i];
                 while (entry != null) {
-                    if (value.equals(entry.value)) {
+                    if (areEqualValues(value, entry.value)) {
                         return true;
                     }
                     entry = entry.next;
                 }
             }
         } else {
-            for (int i = elementData.length; --i >= 0;) {
+            for (int i = 0; i < elementData.length; i++) {
                 Entry<K, V> entry = elementData[i];
                 while (entry != null) {
                     if (entry.value == null) {
@@ -418,9 +467,8 @@
      * 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
      */
     @Override
     public Set<Map.Entry<K, V>> entrySet() {
@@ -429,54 +477,49 @@
 
     /**
      * 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);
-        }
+        Entry<K, V> m = getEntry(key);
         if (m != null) {
             return m.value;
         }
         return null;
     }
 
+    final Entry<K, V> getEntry(Object key) {
+        Entry<K, V> m;
+        if (key == null) {
+            m = findNullKeyEntry();
+        } else {
+            int hash = computeHashCode(key);
+            int index = hash & (elementData.length - 1);
+            m = findNonNullKeyEntry(key, index, hash);
+        }
+        return m;
+    }
+
     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;
-                    }
-                }
+            while (m != null && (m.origKeyHash != keyHash || !keyString.equals(m.key))) {
                 m = m.next;
             }
         } else {
-            while (m != null) {
-                if (m.origKeyHash == keyHash) {
-                    if (key.equals(m.key)) {
-                        return m;
-                    }
-                }
+            while (m != null && (m.origKeyHash != keyHash || !areEqualKeys(key, m.key))) {
                 m = m.next;
             }
         }
-        return null;
+        return m;
         // END android-changed
     }
 
@@ -489,11 +532,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
      */
     @Override
     public boolean isEmpty() {
@@ -504,9 +546,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() {
@@ -535,12 +576,7 @@
 
                 @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 new KeyIterator<K,V> (HashMap.this);
                 }
             };
         }
@@ -549,21 +585,20 @@
 
     /**
      * 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);
     }
 
-    private V putImpl(K key, V value) {
+    V putImpl(K key, V value) {
         Entry<K,V> entry;
         if(key == null) {
             entry = findNullKeyEntry();
@@ -572,17 +607,17 @@
                 if (++elementCount > threshold) {
                     rehash();
                 }
-                entry = createHashedEntry(key, 0, 0);
+                entry = createHashedEntry(null, 0, 0);
             }
         } else {
-            int hash = key.hashCode();
-            int index = (hash & 0x7FFFFFFF) % elementData.length;
+            int hash = computeHashCode(key);
+            int index = hash & (elementData.length - 1);
             entry = findNonNullKeyEntry(key, index, hash);
             if (entry == null) {
                 modCount++;
                 if (++elementCount > threshold) {
                     rehash();
-                    index = (hash & 0x7FFFFFFF) % elementData.length;
+                    index = hash & (elementData.length - 1);
                 }
                 entry = createHashedEntry(key, index, hash);
             }
@@ -611,10 +646,11 @@
      * 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
+     * @throws NullPointerException
+     *             if {@code map} is {@code null}.
      */
     @Override
     public void putAll(Map<? extends K, ? extends V> map) {
@@ -634,13 +670,13 @@
     }
 
     void rehash(int capacity) {
-        int length = (capacity == 0 ? 1 : capacity << 1);
+        int length = calculateCapacity((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;
+                int index = entry.origKeyHash & (length - 1);
                 Entry<K, V> next = entry.next;
                 entry.next = newData[index];
                 newData[index] = entry;
@@ -648,7 +684,7 @@
             }
         }
         elementData = newData;
-        computeMaxSize();
+        computeThreshold();
     }
 
     void rehash() {
@@ -657,12 +693,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) {
@@ -673,15 +708,35 @@
         return null;
     }
 
-    Entry<K, V> removeEntry(Object key) {
+    /*
+     * Remove the given entry from the hashmap.
+     * Assumes that the entry is in the map.
+     */
+    final void removeEntry(Entry<K, V> entry) {
+        int index = entry.origKeyHash & (elementData.length - 1);
+        Entry<K, V> m = elementData[index];
+        if (m == entry) {
+            elementData[index] = entry.next;
+        } else {
+            while (m.next != entry) {
+                m = m.next;
+            }
+            m.next = entry.next;
+
+        }
+        modCount++;
+        elementCount--;
+    }
+
+    final 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;
+            int hash = computeHashCode(key);
+            index = hash & (elementData.length - 1);
             entry = elementData[index];
-            while (entry != null && !(entry.origKeyHash == hash && key.equals(entry.key))) {
+            while (entry != null && !(entry.origKeyHash == hash && areEqualKeys(key, entry.key))) {
                 last = entry;
                 entry = entry.next;
             }
@@ -707,9 +762,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() {
@@ -727,16 +781,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() {
@@ -759,12 +810,7 @@
 
                 @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 new ValueIterator<K,V> (HashMap.this);
                 }
             };
         }
@@ -793,10 +839,25 @@
         elementCount = stream.readInt();
         for (int i = elementCount; --i >= 0;) {
             K key = (K) stream.readObject();
-            int index = (null == key) ? 0 : (key.hashCode() & 0x7FFFFFFF)
-                    % length;
+            int index = (null == key) ? 0 : (computeHashCode(key) & (length - 1));
             createEntry(key, index, (V) stream.readObject());
         }
     }
 
+    /*
+     * Contract-related functionality
+     */
+    static int computeHashCode(Object key) {
+        return key.hashCode();
+}
+
+    static boolean areEqualKeys(Object key1, Object key2) {
+        return (key1 == key2) || key1.equals(key2);
+    }
+
+    static boolean areEqualValues(Object value1, Object value2) {
+        return (value1 == value2) || value1.equals(value2);
+    }
+
+
 }
diff --git a/libcore/luni/src/main/java/java/util/HashSet.java b/libcore/luni/src/main/java/java/util/HashSet.java
index fe89109..dca764f 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() {
@@ -221,7 +206,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..b23364d 100644
--- a/libcore/luni/src/main/java/java/util/Hashtable.java
+++ b/libcore/luni/src/main/java/java/util/Hashtable.java
@@ -31,12 +31,11 @@
  * 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.
- * 
+ *
  * @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>,
@@ -68,6 +67,21 @@
         }
     };
 
+    private static final Iterator<?> EMPTY_ITERATOR = new Iterator<Object>() {
+
+        public boolean hasNext() {
+            return false;
+        }
+
+        public Object next() {
+            throw new NoSuchElementException();
+        }
+
+        public void remove() {
+            throw new IllegalStateException();
+        }
+    };
+
     private static <K, V> Entry<K, V> newEntry(K key, V value, int hash) {
         return new Entry<K, V>(key, value);
     }
@@ -121,16 +135,16 @@
         }
     }
 
-    private final class HashIterator<E> implements Iterator<E> {
-        private int position, expectedModCount;
+    private class HashIterator<E> implements Iterator<E> {
+        int position, expectedModCount;
 
-        private final MapEntry.Type<E, K, V> type;
+        final MapEntry.Type<E, K, V> type;
 
-        private Entry<K, V> lastEntry;
+        Entry<K, V> lastEntry;
 
-        private int lastPosition;
+        int lastPosition;
 
-        private boolean canRemove = false;
+        boolean canRemove = false;
 
         HashIterator(MapEntry.Type<E, K, V> value) {
             type = value;
@@ -218,47 +232,9 @@
         }
     }
 
-    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();
-        }
-    }
-
     /**
      * Constructs a new {@code Hashtable} using the default capacity and load
      * factor.
-     * 
-     * @since Android 1.0
      */
     public Hashtable() {
         this(11);
@@ -267,10 +243,9 @@
     /**
      * 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) {
@@ -287,12 +262,11 @@
     /**
      * 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) {
@@ -309,10 +283,9 @@
     /**
      * 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);
@@ -327,10 +300,9 @@
     /**
      * 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
      */
     public synchronized void clear() {
         elementCount = 0;
@@ -341,17 +313,16 @@
     /**
      * 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() {
         try {
             Hashtable<K, V> hashtable = (Hashtable<K, V>) super.clone();
-            hashtable.elementData = elementData.clone();
+            hashtable.elementData = new Entry[elementData.length];
             Entry<K, V> entry;
             for (int i = elementData.length; --i >= 0;) {
                 if ((entry = elementData[i]) != null) {
@@ -371,14 +342,13 @@
     /**
      * 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 #containsKey
      * @see java.lang.Object#equals
-     * @since Android 1.0
      */
     public synchronized boolean contains(Object value) {
         if (value == null) {
@@ -388,7 +358,7 @@
         for (int i = elementData.length; --i >= 0;) {
             Entry<K, V> entry = elementData[i];
             while (entry != null) {
-                if (value.equals(entry.value)) {
+                if (entry.value.equals(value)) {
                     return true;
                 }
                 entry = entry.next;
@@ -400,14 +370,13 @@
     /**
      * 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;
@@ -415,12 +384,11 @@
 
     /**
      * 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);
@@ -430,12 +398,11 @@
      * 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")
@@ -443,7 +410,11 @@
         if (elementCount == 0) {
             return (Enumeration<V>) EMPTY_ENUMERATION;
         }
-        return new HashEnumerator<V>(false);
+        return new HashEnumIterator<V>(new MapEntry.Type<V, K, V>() {
+            public V get(MapEntry<K, V> entry) {
+                return entry.value;
+            }
+        }, true);
     }
 
     /**
@@ -451,18 +422,15 @@
      * 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;
-                        }
+                        return elementCount;
                     }
 
                     @Override
@@ -473,25 +441,20 @@
                     @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;
+                        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);
-                        }
+                        Entry<K, V> entry = getEntry(((Map.Entry<K, V>) object)
+                                .getKey());
+                        return object.equals(entry);
                     }
 
                     @Override
@@ -511,13 +474,12 @@
      * 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) {
@@ -544,13 +506,12 @@
     /**
      * 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
      */
     @Override
     public synchronized V get(Object key) {
@@ -586,10 +547,15 @@
         while (it.hasNext()) {
             Map.Entry<K, V> entry = it.next();
             Object key = entry.getKey();
+            if (key == this) {
+                continue;
+            }
             Object value = entry.getValue();
-            int hash = (key != this ? key.hashCode() : 0)
-                    ^ (value != this ? (value != null ? value.hashCode() : 0)
-                            : 0);
+            if (value == this) {
+                continue;
+            }
+            int hash = (key != null ? key.hashCode() : 0)
+                    ^ (value != null ? value.hashCode() : 0);
             result += hash;
         }
         return result;
@@ -597,11 +563,10 @@
 
     /**
      * 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 #size
-     * @since Android 1.0
      */
     @Override
     public synchronized boolean isEmpty() {
@@ -612,12 +577,11 @@
      * 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")
@@ -625,31 +589,30 @@
         if (elementCount == 0) {
             return (Enumeration<K>) EMPTY_ENUMERATION;
         }
-        return new HashEnumerator<K>(true);
+        return new HashEnumIterator<K>(new MapEntry.Type<K, K, V>() {
+            public K get(MapEntry<K, V> entry) {
+                return entry.key;
+            }
+        }, 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);
-                }
+                return containsKey(object);
             }
 
             @Override
             public int size() {
-                synchronized (Hashtable.this) {
-                    return elementCount;
-                }
+                return elementCount;
             }
 
             @Override
@@ -659,18 +622,19 @@
 
             @Override
             public boolean remove(Object key) {
-                synchronized (Hashtable.this) {
-                    if (containsKey(key)) {
-                        Hashtable.this.remove(key);
-                        return true;
-                    }
-                    return false;
+                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>() {
+                if (this.size() == 0) {
+                    return (Iterator<K>) EMPTY_ITERATOR;
+                }
+                return new HashEnumIterator<K>(new MapEntry.Type<K, K, V>() {
                     public K get(MapEntry<K, V> entry) {
                         return entry.key;
                     }
@@ -679,11 +643,89 @@
         }, this);
     }
 
+    class HashEnumIterator<E> extends HashIterator<E> implements Enumeration<E> {
+
+        private boolean isEnumeration = false;
+
+        int start;
+
+        Entry<K, V> entry;
+
+        HashEnumIterator(MapEntry.Type<E, K, V> value) {
+            super(value);
+        }
+
+        HashEnumIterator(MapEntry.Type<E, K, V> value, boolean isEnumeration) {
+            super(value);
+            this.isEnumeration = isEnumeration;
+            start = lastSlot + 1;
+        }
+
+        public boolean hasMoreElements() {
+            if (isEnumeration) {
+                if (entry != null) {
+                    return true;
+                }
+                while (start > firstSlot) {
+                    if (elementData[--start] != null) {
+                        entry = elementData[start];
+                        return true;
+                    }
+                }
+                return false;
+            }
+            // iterator
+            return super.hasNext();
+        }
+
+        public boolean hasNext() {
+            if (isEnumeration) {
+                return hasMoreElements();
+            }
+            // iterator
+            return super.hasNext();
+        }
+
+        public E next() {
+            if (isEnumeration) {
+                if (expectedModCount == modCount) {
+                    return nextElement();
+                } else {
+                    throw new ConcurrentModificationException();
+                }
+            }
+            // iterator
+            return super.next();
+        }
+
+        @SuppressWarnings("unchecked")
+        public E nextElement() {
+            if (isEnumeration) {
+                if (hasMoreElements()) {
+                    Object result = type.get(entry);
+                    entry = entry.next;
+                    return (E) result;
+                }
+                throw new NoSuchElementException();
+            }
+            // iterator
+            return super.next();
+        }
+
+        public void remove() {
+            if (isEnumeration) {
+                throw new UnsupportedOperationException();
+            } else {
+                super.remove();
+            }
+        }
+    }
+
     /**
      * 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,7 +736,6 @@
      * @see #get
      * @see #keys
      * @see java.lang.Object#equals
-     * @since Android 1.0
      */
     @Override
     public synchronized V put(K key, V value) {
@@ -731,10 +772,9 @@
 
     /**
      * 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()) {
@@ -745,8 +785,6 @@
     /**
      * 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;
@@ -781,14 +819,13 @@
     /**
      * 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) {
@@ -817,11 +854,10 @@
 
     /**
      * 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
      */
     @Override
     public synchronized int size() {
@@ -830,9 +866,8 @@
 
     /**
      * Returns the string representation of this {@code Hashtable}.
-     * 
+     *
      * @return the string representation of this {@code Hashtable}.
-     * @since Android 1.0
      */
     @Override
     public synchronized String toString() {
@@ -874,25 +909,20 @@
      * 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);
-                        }
+                        return Hashtable.this.contains(object);
                     }
 
                     @Override
                     public int size() {
-                        synchronized (Hashtable.this) {
-                            return elementCount;
-                        }
+                        return elementCount;
                     }
 
                     @Override
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..ed526d8 100644
--- a/libcore/luni/src/main/java/java/util/LinkedHashMap.java
+++ b/libcore/luni/src/main/java/java/util/LinkedHashMap.java
@@ -17,7 +17,6 @@
 
 package java.util;
 
-
 /**
  * LinkedHashMap is a variant of HashMap. Its entries are kept in a
  * doubly-linked list. The iteration order is, by default, the order in which
@@ -46,8 +45,8 @@
  * 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
+ *
+ * @since 1.4
  */
 public class LinkedHashMap<K, V> extends HashMap<K, V> {
 
@@ -59,8 +58,6 @@
 
     /**
      * Constructs a new empty {@code LinkedHashMap} instance.
-     * 
-     * @since Android 1.0
      */
     public LinkedHashMap() {
         super();
@@ -71,12 +68,11 @@
     /**
      * Constructs a new {@code LinkedHashMap} instance with the specified
      * capacity.
-     * 
+     *
      * @param s
      *            the initial capacity of this map.
-     * @exception IllegalArgumentException
-     *                when the capacity is less than zero.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *                if the capacity is less than zero.
      */
     public LinkedHashMap(int s) {
         super(s);
@@ -87,7 +83,7 @@
     /**
      * Constructs a new {@code LinkedHashMap} instance with the specified
      * capacity and load factor.
-     * 
+     *
      * @param s
      *            the initial capacity of this map.
      * @param lf
@@ -95,7 +91,6 @@
      * @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);
@@ -107,7 +102,7 @@
     /**
      * Constructs a new {@code LinkedHashMap} instance with the specified
      * capacity, load factor and a flag specifying the ordering behavior.
-     * 
+     *
      * @param s
      *            the initial capacity of this hash map.
      * @param lf
@@ -120,7 +115,6 @@
      * @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);
@@ -132,10 +126,9 @@
     /**
      * Constructs a new {@code LinkedHashMap} instance containing the mappings
      * from the specified map. The order of the elements is preserved.
-     * 
+     *
      * @param m
      *            the mappings to add.
-     * @since Android 1.0
      */
     public LinkedHashMap(Map<? extends K, ? extends V> m) {
         accessOrder = false;
@@ -144,58 +137,47 @@
         putAll(m);
     }
 
-    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;
+    private static class AbstractMapIterator<K, V>  {
+        int expectedModCount;
+        LinkedHashMapEntry<K, V>  futureEntry;
+        LinkedHashMapEntry<K, V>  currentEntry;
+        final LinkedHashMap<K, V> associatedMap;
+
+        AbstractMapIterator(LinkedHashMap<K, V> map) {
+            expectedModCount = map.modCount;
+            futureEntry = map.head;
+            associatedMap = map;
         }
 
-        @Override
         public boolean hasNext() {
-            return (entry != null);
+            return (futureEntry != null);
         }
 
-        @Override
-        public E next() {
+        final void checkConcurrentMod() throws ConcurrentModificationException {
+            if (expectedModCount != associatedMap.modCount) {
+                throw new ConcurrentModificationException();
+            }
+        }
+
+        final void makeNext() {
             checkConcurrentMod();
             if (!hasNext()) {
                 throw new NoSuchElementException();
             }
-            E result = type.get(entry);
-            lastEntry = entry;
-            entry = ((LinkedHashMapEntry<KT, VT>)entry).chainForward;
-            canRemove = true;
-            return result;
+            currentEntry = futureEntry;
+            futureEntry = futureEntry.chainForward;
         }
 
-        @Override
         public void remove() {
             checkConcurrentMod();
-            if (!canRemove) {
+            if (currentEntry==null) {
                 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;
+            associatedMap.removeEntry(currentEntry);
+            LinkedHashMapEntry<K, V> lhme =  currentEntry;
+            LinkedHashMapEntry<K, V> p = lhme.chainBackward;
+            LinkedHashMapEntry<K, V> n = lhme.chainForward;
+            LinkedHashMap<K, V> lhm = associatedMap;
             if (p != null) {
                 p.chainForward = n;
                 if (n != null) {
@@ -211,23 +193,56 @@
                     lhm.tail = null;
                 }
             }
-            associatedMap.elementCount--;
+            currentEntry = null;
             expectedModCount++;
         }
     }
 
-    static final class LinkedHashMapEntrySet<KT, VT> extends HashMapEntrySet<KT, VT> {
+    private static class EntryIterator <K, V> extends AbstractMapIterator<K, V> implements Iterator<Map.Entry<K, V>> {
+
+        EntryIterator (LinkedHashMap<K, V> map) {
+            super(map);
+        }
+
+        public Map.Entry<K, V> next() {
+            makeNext();
+            return currentEntry;
+        }
+    }
+
+    private static class KeyIterator <K, V> extends AbstractMapIterator<K, V> implements Iterator<K> {
+
+        KeyIterator (LinkedHashMap<K, V> map) {
+            super(map);
+        }
+
+        public K next() {
+            makeNext();
+            return currentEntry.key;
+        }
+    }
+
+    private static class ValueIterator <K, V> extends AbstractMapIterator<K, V> implements Iterator<V> {
+
+        ValueIterator (LinkedHashMap<K, V> map) {
+            super(map);
+        }
+
+        public V next() {
+            makeNext();
+            return currentEntry.value;
+        }
+    }
+
+    static final class LinkedHashMapEntrySet<KT, VT> extends
+            HashMapEntrySet<KT, VT> {
         public LinkedHashMapEntrySet(LinkedHashMap<KT, VT> lhm) {
             super(lhm);
         }
 
         @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());
+        public Iterator<Map.Entry<KT, VT>> iterator() {
+            return new EntryIterator<KT,VT>((LinkedHashMap<KT, VT>) hashMap());
         }
     }
 
@@ -246,11 +261,11 @@
             chainBackward = null;
         }
 
-
         @Override
         @SuppressWarnings("unchecked")
         public Object clone() {
-            LinkedHashMapEntry<K, V> entry = (LinkedHashMapEntry<K, V>) super.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;
@@ -262,6 +277,33 @@
     }
 
     @Override
+    public boolean containsValue(Object value) {
+        LinkedHashMapEntry<K, V> entry = head;
+        if (null == value) {
+            while (null != entry) {
+                if (null == entry.value) {
+                    return true;
+                }
+                entry = entry.chainForward;
+            }
+        } else {
+            while (null != entry) {
+                if (value.equals(entry.value)) {
+                    return true;
+                }
+                entry = entry.chainForward;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Create a new element array
+     *
+     * @param s
+     * @return Reference to the element array
+     */
+    @Override
     @SuppressWarnings("unchecked")
     Entry<K, V>[] newElementArray(int s) {
         return new LinkedHashMapEntry[s];
@@ -269,22 +311,21 @@
 
     /**
      * 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;
         if (key == null) {
-            m = (LinkedHashMapEntry<K, V>)findNullKeyEntry();
+            m = (LinkedHashMapEntry<K, V>) findNullKeyEntry();
         } else {
             int hash = key.hashCode();
             int index = (hash & 0x7FFFFFFF) % elementData.length;
-            m = (LinkedHashMapEntry<K, V>)findNonNullKeyEntry(key, index, hash);
+            m = (LinkedHashMapEntry<K, V>) findNonNullKeyEntry(key, index, hash);
         }
         if (m == null) {
             return null;
@@ -321,7 +362,7 @@
         return m;
     }
 
-    Entry<K,V> createHashedEntry(K key, int index, int hash) {
+    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;
@@ -329,22 +370,19 @@
         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
      */
     @Override
     public V put(K key, V value) {
-        V result = putImpl(key,value);
+        V result = putImpl(key, value);
 
         if (removeEldestEntry(head)) {
             remove(head.key);
@@ -352,38 +390,38 @@
 
         return result;
     }
-    
-    V putImpl(K key, V value){
+
+    V putImpl(K key, V value) {
         LinkedHashMapEntry<K, V> m;
-        if (elementCount == 0){
+        if (elementCount == 0) {
             head = tail = null;
         }
         if (key == null) {
-            m = (LinkedHashMapEntry<K, V>)findNullKeyEntry();
+            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'.
+                // 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);
+                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);
+            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);
+                m = (LinkedHashMapEntry<K, V>) createHashedEntry(key, index,
+                        hash);
             } else {
                 linkEntry(m);
             }
@@ -393,7 +431,6 @@
         m.value = value;
         return result;
     }
-    // END android-changed
 
     /*
      * @param m
@@ -448,16 +485,14 @@
             tail.chainForward = m;
             tail = m;
         }
-
     }
 
     /**
      * 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
      */
     @Override
     public Set<Map.Entry<K, V>> entrySet() {
@@ -468,9 +503,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() {
@@ -502,11 +536,7 @@
 
                 @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 new KeyIterator<K,V>(LinkedHashMap.this);
                 }
             };
         }
@@ -524,16 +554,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 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() {
@@ -556,11 +583,7 @@
 
                 @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);
+                    return new ValueIterator<K,V>(LinkedHashMap.this);
                 }
             };
         }
@@ -569,12 +592,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) {
@@ -602,23 +624,21 @@
      * 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) {
+    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() {
@@ -631,25 +651,4 @@
         head = tail = null;
     }
     // END android-changed
-
-    // 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
 }
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..79d7069 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,40 @@
      * <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;
+        BufferedInputStream bis = new BufferedInputStream(in);
 
         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 +320,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 +327,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 +370,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 +388,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 +442,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 +454,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 +482,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 +502,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 +520,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 +540,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 +562,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 +607,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 +640,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 +657,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 +699,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 +720,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 +751,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..104a981 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,9 @@
             }
             output.append("\r\n"); //$NON-NLS-1$
         }
+        if (reqHeader.get("Accept") == null) { //$NON-NLS-1$
+            output.append("Accept: *; */*\r\n"); //$NON-NLS-1$
+        }
         if (httpVersion > 0 && reqHeader.get("Connection") == null) { //$NON-NLS-1$
             output.append("Connection: Keep-Alive\r\n"); //$NON-NLS-1$
         }
@@ -1367,43 +1406,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 +1414,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 +1429,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 +1657,7 @@
     /**
      * Returns the authorization credentials on the base of provided
      * authorization challenge
-     * 
+     *
      * @param challenge
      * @return authorization credentials
      * @throws IOException
@@ -1707,4 +1709,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..eae5261 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;
@@ -233,8 +221,8 @@
     // 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..1ec6240 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,479 @@
     //         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[] addr)
+            throws UnknownHostException {
+        return getHostByAddrImpl(addr);
+    }
+    static native InetAddress getHostByAddrImpl(byte[] addr)
+            throws UnknownHostException;
+
+    public InetAddress getHostByName(String addr,
+            boolean preferIPv6Addresses) throws UnknownHostException {
+        return getHostByNameImpl(addr, preferIPv6Addresses);
+    }
+
+    static native InetAddress getHostByNameImpl(String addr,
+            boolean preferIPv6Addresses) throws UnknownHostException;
+
+    public int getSocketFlags() {
+        return getSocketFlagsImpl();
+    }
+
+    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 +560,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 +569,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..d8b261d 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,28 +24,28 @@
  */
 public class Inet6Util {
 
-    /**
-     * Creates an byte[] based on an ipAddressString. No error handling is
-     * performed here.
-     */
-    public static byte[] createByteArrayFromIPAddressString(
-            String ipAddressString) {
+	/**
+	 * Creates an byte[] based on an ipAddressString. No error handling is
+	 * performed here.
+	 */
+	public static byte[] createByteArrayFromIPAddressString(
+			String ipAddressString) {
 
-        if (isValidIPV4Address(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;
-            }
+			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) == '[') {
+			return byteAddress;
+		}
+
+		if (ipAddressString.charAt(0) == '[') {
             ipAddressString = ipAddressString.substring(1, ipAddressString.length() - 1);
         }
 
@@ -63,105 +63,105 @@
          * 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();
+		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 (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);
-        }
+		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;
+		// 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 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");
-            }
-        }
+		// 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];
+		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);
-        }
+		// 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++) {
+		// 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;
-            }
-        }
+		// 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 (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;
+		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));
-        }
+	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));
-            }
+		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
@@ -189,131 +189,129 @@
             }
             // END android-changed
             return buffer.toString();
-        }
-        return null;
-    }
+		}
+		return null;
+	}
 
-    /** Converts a 4 character hex word into a 2 byte word equivalent */
-    public static void convertToBytes(String hexWord, byte ipByteArray[],
-            int byteIndex) {
+	/** 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;
+		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));
-        }
+		// 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);
-        }
+		// 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));
-        }
+		// 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);
-    }
+		// 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) {
+	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;
-        }
+		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;
-    }
+		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[]) {
+	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;
-            }
-        }
+		// 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;
-        }
+		if (ipAddress[10] != -1 || ipAddress[11] != -1) {
+			return false;
+		}
 
-        return true;
+		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;
-    }
+	/**
+	 * 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);
-    }
+	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 +323,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/org_apache_harmony_luni_platform_OSMemory.cpp b/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSMemory.cpp
index c5e92bb..3e31743 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);
 }
 
 /*
@@ -577,6 +611,46 @@
     { "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..cce822a
--- 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
@@ -33,9 +33,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,6 +149,9 @@
 // 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;
@@ -238,30 +245,59 @@
 }
 
 /**
- * Converts a native address structure to a 4-byte array. 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 structInToJavaAddress(
-        JNIEnv *env, struct in_addr *address, jbyteArray java_address) {
+static jbyteArray socketAddressToAddressBytes(JNIEnv *env,
+        struct sockaddr_storage *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;
+    return byteArray;
+}
 
-    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;
+/**
+ * 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 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;
+    }
 }
 
 /**
@@ -269,68 +305,79 @@
  * 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 = socketAddressToAddressBytes(env, sockaddress);
+    if (byteArray == NULL)  // Exception has already been thrown.
+        return NULL;
 
-    ipaddress = (jbyteArray)env->GetObjectField(inetaddress,
-            gCachedFields.iaddr_ipaddress);
-
-    if (structInToJavaAddress(env, &sockaddress->sin_addr, ipaddress) < 0) {
-        return -1;
-    }
-
-    *port = ntohs(sockaddress->sin_port);
-
-    return 0;
+    return env->CallStaticObjectMethod(gCachedFields.iaddr_class,
+            gCachedFields.iaddr_getbyaddress, byteArray);
 }
 
 /**
- * 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
+ *
+ * @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, struct 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));
-
-    sockaddress->sin_family = AF_INET;
-    sockaddress->sin_port = htons(port);
-
-    if (javaAddressToStructIn(env, ipaddress, &(sockaddress->sin_addr)) < 0) {
-        return -1;
+    if (addressByteArray == NULL) {
+      throwNullPointerException(env);
+      return -1;
     }
 
-    return 0;
-}
-
-static jobject structInToInetAddress(JNIEnv *env, struct in_addr *address) {
-    jbyteArray bytes;
-    int success;
-
-    bytes = env->NewByteArray(4);
-
-    if (bytes == NULL) {
-        return NULL;
+    // Get the raw IP address bytes.
+    jbyte *addressBytes = env->GetByteArrayElements(addressByteArray, NULL);
+    if (addressBytes == NULL) {
+      throwNullPointerException(env);
+      return -1;
     }
 
-    if (structInToJavaAddress(env, address, bytes) < 0) {
-        return NULL;
+    // Convert the IP address bytes to the proper IP address type.
+    size_t addressLength = env->GetArrayLength(addressByteArray);
+    int result = 0;
+    if (addressLength == 4) {
+        // IPv4 address.
+        struct sockaddr_in *sin = (struct sockaddr_in *) sockaddress;
+        memset(sin, 0, sizeof(struct sockaddr_in));
+        sin->sin_family = AF_INET;
+        sin->sin_port = htons(port);
+        memcpy(&sin->sin_addr.s_addr, addressBytes, 4);
+    } else if (addressLength == 16) {
+        // IPv6 address.
+        struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sockaddress;
+        memset(sin6, 0, sizeof(struct sockaddr_in6));
+        sin6->sin6_family = AF_INET6;
+        sin6->sin6_port = htons(port);
+        memcpy(&sin6->sin6_addr.s6_addr, addressBytes, 16);
+    } else {
+        // Unknown address family.
+        throwSocketException(env, SOCKERR_BADAF);
+        result = -1;
     }
-
-    return env->CallStaticObjectMethod(gCachedFields.iaddr_class,
-            gCachedFields.iaddr_getbyaddress, bytes);
+    env->ReleaseByteArrayElements(addressByteArray, addressBytes, 0);
+    return result;
 }
 
 /**
@@ -427,15 +474,77 @@
 }
 
 /**
- * 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;
+}
+
+/**
+ * Convert a sockaddr_storage structure to a string for logging purposes.
+ *
+ * @param address pointer to sockaddr_storage structure to print
+ *
+ * @return a string with the textual representation of the address.
+ *
+ * @note Returns a statically allocated buffer, so is not thread-safe.
+ */
+static char *socketAddressToString(struct sockaddr_storage *address) {
+    static char invalidString[] = "<invalid>";
+    static char ipString[INET6_ADDRSTRLEN + sizeof("[]:65535")];
+
+    char tmp[INET6_ADDRSTRLEN];
+    int port;
+    // 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 = (address->ss_family == AF_INET) ?
+            sizeof(sockaddr_in) : sizeof(sockaddr_in6);
+    int result = getnameinfo((struct sockaddr *)address,
+            size, tmp, sizeof(tmp), NULL, 0,
+            NI_NUMERICHOST);
+
+    if (result != 0)
+        return invalidString;
+
+    if (address->ss_family == AF_INET6) {
+        struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) address;
+        port = ntohs(sin6->sin6_port);
+        sprintf(ipString, "[%s]:%d", tmp, port);
+        return ipString;
+    } else if (address->ss_family == AF_INET) {
+        struct sockaddr_in *sin = (struct sockaddr_in *) address;
+        port = ntohs(sin->sin_port);
+        sprintf(ipString, "%s:%d", tmp, port);
+        return ipString;
+    } else {
+        return invalidString;
+    }
 }
 
 /**
@@ -728,7 +837,6 @@
                 }
 
             } else if (0 > result) {
-                log_socket_close(handle, result);
                 throwSocketException(env, result);
             }
             poll = 0;
@@ -745,7 +853,6 @@
 
                 continue; // try again
             } else if (0 > result) {
-                log_socket_close(handle, result);
                 throwSocketException(env, result);
             }
             poll = 0;
@@ -756,6 +863,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
@@ -803,6 +928,77 @@
 }
 
 /**
+ * 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 ipv4ToMappedAddress(struct sockaddr_storage *address,
+        struct sockaddr_storage *outputAddress, bool mapUnspecified) {
+  memset(outputAddress, 0, sizeof(struct sockaddr_storage));
+  const struct sockaddr_in *sin = ((struct sockaddr_in *) address);
+  struct sockaddr_in6 *sin6 = ((struct sockaddr_in6 *) outputAddress);
+  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;
+}
+
+/**
+ * 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) {
+    struct sockaddr_storage mappedAddress;
+    struct sockaddr_storage *realAddress;
+    if (socketAddress->ss_family == AF_INET &&
+        getSocketAddressFamily(socket) == AF_INET6) {
+        ipv4ToMappedAddress(socketAddress, &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) {
+        ipv4ToMappedAddress(socketAddress, &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
  * proceed on certain platforms. The caller must first call with
@@ -823,7 +1019,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 +1034,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 +1051,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 +1162,89 @@
     return SOCKERR_ARGSINVALID;
 }
 
+
+/**
+ * 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 = IPPROTO_IP;
+            break;
+        case AF_INET6:
+            option = ipv6Option;
+            protocol = IPPROTO_IPV6;
+            break;
+        default:
+            errno = EAFNOSUPPORT;
+            return -1;
+    }
+    if (action == SOCKOPT_GET) {
+        return getsockopt(socket, protocol, option, &optionValue, optionLength);
+    } else if (action == SOCKOPT_SET) {
+        return setsockopt(socket, protocol, option, &optionValue,
+                          *optionLength);
+    } else {
+        errno = EINVAL;
+        return -1;
+    }
+}
+
+/*
+ * 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, IPPROTO_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, IPPROTO_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 +1268,112 @@
  */
 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, IPPROTO_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);
-
-        ipmreqP.imr_interface.s_addr = htonl(INADDR_ANY);
-
-        /*
-         * 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;
-                }
-
-                memcpy(&(ipmreqP.imr_interface.s_addr), &(sockaddrP.sin_addr), 4);
-
-            }
+        struct ip_mreqn ipv4Request;
+        struct ipv6_mreq ipv6Request;
+        void *multicastRequest;
+        socklen_t requestLength;
+        int level;
+        int family = getSocketAddressFamily(handle);
+        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 = IPPROTO_IP;
+                break;
+            case AF_INET6:
+                requestLength = sizeof(ipv6Request);
+                memset(&ipv6Request, 0, requestLength);
+                ipv6Request.ipv6mr_multiaddr =
+                        ((struct sockaddr_in6 *) &sockaddrP)->sin6_addr;
+                ipv6Request.ipv6mr_interface = interfaceIndex;
+                multicastRequest = &ipv6Request;
+                level = IPPROTO_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;
@@ -1339,38 +1622,48 @@
 
 }
 
-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
+ *
+ * @return the socket file descriptor, or -1 on failure
+ *
+ */
+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);
+    }
+    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 +1672,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 +1698,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 +1728,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 +1746,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 +1763,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 +1789,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 +1799,6 @@
         return 0;
     }
 
-    add_send_stats(handle, result);
     return result;
 }
 
@@ -1539,13 +1828,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 +1870,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 +1929,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 +1942,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 +2060,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 +2074,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 +2121,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 +2161,6 @@
 
     if (ret < 0) {
         int err = convertError(errno);
-        log_socket_close(handle, err);
         throwSocketException(env, err);
         return;
     }
@@ -1928,9 +2176,8 @@
     int result;
 
     handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
     if (handle == 0 || handle == -1) {
-        throwSocketException(env, SOCKERR_BADSOCKET);
+        throwSocketException(env, SOCKERR_BADDESC);
         return 0;
     }
 
@@ -1943,7 +2190,6 @@
         } else if (SOCKERR_INTERRUPTED == result) {
             continue;
         } else if (0 > result) {
-            log_socket_close(handle, result);
             throwSocketException(env, result);
             return 0;
         }
@@ -1953,11 +2199,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 +2209,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 +2223,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 +2299,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 +2309,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 +2329,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 +2352,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 +2389,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 = socketAddressToAddressBytes(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 +2440,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 +2481,6 @@
     if ( packet != NULL) {
         env->SetIntField(packet, gCachedFields.dpack_length, actualLength);
     }
-    add_recv_stats(handle, actualLength);
     return actualLength;
 }
 
@@ -2315,7 +2498,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 +2514,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 +2521,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 +2578,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 +2602,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 +2651,6 @@
      * to the Java input stream
      */
     if (0 < result) {
-        add_recv_stats(handle, result);
         return result;
     } else if (0 == result) {
         return -1;
@@ -2516,7 +2661,6 @@
                               netLookupErrorString(SOCKERR_TIMEOUT));
         } else {
             int err = convertError(errno);
-            log_socket_close(handle, err);
             throwSocketException(env, err);
         }
         return 0;
@@ -2560,7 +2704,6 @@
             }
             env->ReleaseByteArrayElements(data, message, 0);
             int err = convertError(result);
-            log_socket_close(handle, err);
             throwSocketException(env, err);
             return 0;
         }
@@ -2568,7 +2711,6 @@
     }
 
     env->ReleaseByteArrayElements(data, message, 0);
-    add_send_stats(handle, sent);
     return sent;
 }
 
@@ -2590,7 +2732,6 @@
 
     if (ret < 0) {
         int err = convertError(errno);
-        log_socket_close(handle, err);
         throwSocketException(env, err);
         return;
     }
@@ -2613,7 +2754,6 @@
 
     if (ret < 0) {
         int err = convertError(errno);
-        log_socket_close(handle, err);
         throwSocketException(env, err);
         return;
     }
@@ -2625,26 +2765,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 +2796,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 +2818,6 @@
     }
 
     free(message);
-    add_send_stats(handle, sent);
     return sent;
 }
 
@@ -2757,10 +2890,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 +2932,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 +2972,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 +2986,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,7 +3026,9 @@
             if ((anOption >> 16) & BROKEN_MULTICAST_TTL) {
                 return newJavaLangByte(env, 0);
             }
-            result = getsockopt(handle, IPPROTO_IP, IP_MULTICAST_TTL, &byteValue, &byteSize);
+            result = getOrSetSocketOption(SOCKOPT_GET, handle, IP_MULTICAST_TTL,
+                                          IPV6_MULTICAST_HOPS, &byteValue,
+                                          &byteSize);
             if (0 != result) {
                 throwSocketException(env, convertError(errno));
                 return NULL;
@@ -2912,7 +3044,42 @@
                 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, IPPROTO_IP, IP_MULTICAST_IF,
+                                        &multicastRequest, &optionLength);
+                    if (result == 0)
+                        interfaceIndex = multicastRequest.imr_ifindex;
+                    break;
+                case AF_INET6:
+                    optionLength = sizeof(interfaceIndex);
+                    result = getsockopt(handle, IPPROTO_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 +3130,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 +3141,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 +3172,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 +3187,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 +3199,7 @@
 
     handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
     if (handle == 0 || handle == -1) {
-        throwSocketException(env, SOCKERR_BADSOCKET);
+        throwSocketException(env, SOCKERR_BADDESC);
         return;
     }
 
@@ -3056,11 +3229,13 @@
             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);
+            result = getOrSetSocketOption(SOCKOPT_SET, handle, IP_MULTICAST_TTL,
+                                          IPV6_MULTICAST_HOPS, &byteVal,
+                                          &byteSize);
             if (0 != result) {
                 throwSocketException(env, convertError(errno));
                 return;
@@ -3071,23 +3246,28 @@
         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.
+            if (getSocketAddressFamily(handle) != 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));
+            struct sockaddr_in *sin = (struct sockaddr_in *) &sockVal;
+            mcast_req.imr_address = sin->sin_addr;
             result = setsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF,
                                 &mcast_req, sizeof(mcast_req));
             if (0 != result) {
@@ -3097,6 +3277,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 +3367,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 +3379,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,8 +3435,6 @@
         return;
     }
 
-    log_socket_close(handle, SOCKET_CLOSE_LOCAL);
-
     jniSetFileDescriptorOfFD(env, fileDescriptor, -1);
 
     close(handle);
@@ -3311,6 +3529,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");
 
@@ -3586,7 +3805,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 +3823,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 +3833,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                  },
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/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/ClassTest.java b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ClassTest.java
index 14ca1ad..3097fbe 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,6 +838,8 @@
         args = {}
     )
     public void test_getClassLoader() {
+        // this fails if ClassTest.class was loaded by the regular classloader,
+        // but passes if it was loaded by the boot class loader.
 
         assertEquals(ExtendTestClass.class.getClassLoader(),
                          PublicTestClass.class.getClassLoader());
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/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/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/URLConnectionTest.java b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLConnectionTest.java
index c803d3b..bcd73d8 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
@@ -1069,8 +1069,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 +1610,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/api/java/io/FileTest.java b/libcore/luni/src/test/java/tests/api/java/io/FileTest.java
index bde5766..2850826 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");
@@ -694,6 +690,8 @@
     )
     @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..b745662 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
@@ -31,6 +31,7 @@
 import java.io.UnsupportedEncodingException;
 import java.nio.charset.Charset;
 import java.nio.charset.CharsetEncoder;
+import java.util.Arrays;
 
 import tests.support.Support_OutputStream;
 
@@ -485,6 +486,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()
      */
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/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/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/MulticastSocketTest.java b/libcore/luni/src/test/java/tests/api/java/net/MulticastSocketTest.java
index 86e298c..997055b 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()));
 
     }
 
@@ -608,11 +613,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 +638,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 +720,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();
@@ -942,7 +945,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 +1018,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()));
     }
 
     /**
@@ -1162,24 +1164,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 +1588,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/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/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/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..8f3508d 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,28 @@
     // }
     // 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) {
+        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/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/Preferences.java b/libcore/prefs/src/main/java/java/util/prefs/Preferences.java
index b7a0c70..719c89a 100644
--- a/libcore/prefs/src/main/java/java/util/prefs/Preferences.java
+++ b/libcore/prefs/src/main/java/java/util/prefs/Preferences.java
@@ -1006,15 +1006,11 @@
     
     //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$
     }
 
     /**
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..0c61e75 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
@@ -32,15 +32,25 @@
 @TestTargetClass(java.util.prefs.Preferences.class)
 public class FilePreferencesImplTest extends TestCase {
 
-    public FilePreferencesImplTest() {
-        super();
+    String oldUserHome = System.getProperty("user.home");
+    String oldJavaHome = System.getProperty("java.home");
+
+    protected void setUp() throws Exception {
+        super.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();
     }
-    
-    @Override
-    protected void setUp(){
-    }
-    @Override
-    protected void tearDown(){
+
+    protected void tearDown() throws Exception {
+        Preferences.systemRoot().clear();
+        Preferences.userRoot().clear();
+        System.setProperty("user.home", oldUserHome);
+        System.setProperty("java.home", oldJavaHome);
+
+        super.tearDown();
     }
 
     @TestTargets({
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..eab3b14 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
@@ -39,6 +39,27 @@
 
     NodeChangeEvent event;
 
+    String oldUserHome = System.getProperty("user.home");
+    String oldJavaHome = System.getProperty("java.home");
+
+    protected void setUp() throws Exception {
+        super.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();
+    }
+
+    protected void tearDown() throws Exception {
+        Preferences.systemRoot().clear();
+        Preferences.userRoot().clear();
+        System.setProperty("user.home", oldUserHome);
+        System.setProperty("java.home", oldJavaHome);
+
+        super.tearDown();
+    }
+
     @TestTargetNew(
         level = TestLevel.COMPLETE,
         notes = "",
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..0ebf6bb 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
@@ -45,8 +45,8 @@
 @TestTargetClass(Preferences.class)
 public class PreferencesTest extends TestCase {
 
-    private String oldJavaHome;
-    private String oldUserHome;
+    String oldUserHome = System.getProperty("user.home");
+    String oldJavaHome = System.getProperty("java.home");
 
     MockSecurityManager manager = new MockSecurityManager();
 
@@ -81,6 +81,8 @@
                         .getBytes("UTF-8"));
         stream = new MockInputStream(in);
 
+        System.setProperty("user.home", System.getProperty("java.io.tmpdir"));
+        System.setProperty("java.home", System.getProperty("java.io.tmpdir"));
         Preferences.systemRoot().clear();
         Preferences.userRoot().clear();
 
@@ -107,6 +109,8 @@
 
         Preferences.systemRoot().clear();
         Preferences.userRoot().clear();
+        System.setProperty("user.home", oldUserHome);
+        System.setProperty("java.home", oldJavaHome);
     }
 
     @TestTargetNew(
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/text/src/main/java/java/text/RuleBasedCollator.java b/libcore/text/src/main/java/java/text/RuleBasedCollator.java
index 41a51e2..6418962 100644
--- a/libcore/text/src/main/java/java/text/RuleBasedCollator.java
+++ b/libcore/text/src/main/java/java/text/RuleBasedCollator.java
@@ -390,7 +390,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}
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..8f36632 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"
 
 /**
@@ -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/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..42aa3ec 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.
  */
@@ -49,7 +50,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 +290,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 +322,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 +539,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 +554,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 +582,7 @@
         case OP_GOTO:
         case OP_GOTO_16:
         case OP_GOTO_32:
-            flags = kInstrCanBranch;
+            flags = kInstrCanBranch | kInstrUnconditional;
             break;
 
         /* conditional branches */
@@ -603,7 +607,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 +620,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 +651,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 +959,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 +1005,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 +1049,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 +1090,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 +1115,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 +1170,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/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..3e8dbd0
--- /dev/null
+++ b/tests/075-verification-error/expected.txt
@@ -0,0 +1,11 @@
+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 (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..8a0dd15
--- /dev/null
+++ b/tests/075-verification-error/src/Main.java
@@ -0,0 +1,140 @@
+/*
+ * 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 access succeeded\n");
+        } catch (IllegalAccessError iae) {
+            System.out.println("Got expected IllegalAccessError (meth-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..79ad335
--- /dev/null
+++ b/tests/075-verification-error/src/other/InaccessibleClass.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 InaccessibleClass {
+    public static void test() {}
+}
+
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..c598910
--- /dev/null
+++ b/tests/075-verification-error/src2/other/InaccessibleClass.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;
+
+/*package*/ class InaccessibleClass {
+    public static void test() {}
+}
+
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..4696965
--- /dev/null
+++ b/tools/gclog.py
@@ -0,0 +1,204 @@
+#!/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.
+
+#
+# Version 1.0, 29-Apr-2009
+#
+# 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 os
+import re
+import time
+
+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(timestamp, pid, values):
+    """Handle a single dvm_gc_info event"""
+
+    pid = int(pid)
+
+    global_info = parseGlobalInfo(values[0])
+    heap_stats = parseAggHeapStats(values[1])
+    zygote = parseZygoteStats(values[2])
+    external = parseExternalStats(values[3])
+
+    debug = False
+    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 "%s %s(%d) softlim=%dKB, extlim=%dKB, extalloc=%dKB" % \
+            (timestamp, global_info[0], pid, zygote[0]/1024, external[2]/1024, external[3]/1024)
+    print "  freed %d objects / %d bytes in %dms" % \
+            (heap_stats[0], global_info[2], global_info[1])
+
+
+def filterInput(logPipe):
+    """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(match.group(1), match.group(2), ( match.group(3), \
+                    match.group(4), match.group(5), match.group(6) ) )
+
+def start():
+    """Entry point"""
+
+    # launch a logcat and read from it
+    command = 'adb logcat -v time -b events'
+    logPipe = os.popen(command)
+
+    try:
+        filterInput(logPipe)
+    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..f8e393c 100644
--- a/vm/CheckJni.c
+++ b/vm/CheckJni.c
@@ -35,6 +35,116 @@
 
 #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.
+ */
+static void checkCallCommon(const u4* args, JValue* pResult,
+    const Method* method, Thread* self)
+{
+    assert(pResult->l != NULL);
+    ClassObject* objClazz = ((Object*)pResult->l)->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);
+        }
+    }
+}
+
+/*
+ * Check a call into native code.
+ */
+void dvmCheckCallJNIMethod(const u4* args, JValue* pResult,
+    const Method* method, Thread* self)
+{
+    dvmCallJNIMethod(args, pResult, method, self);
+    if (method->shorty[0] == 'L' && !dvmCheckException(self) &&
+        pResult->l != NULL)
+    {
+        checkCallCommon(args, pResult, method, self);
+    }
+}
+
+/*
+ * Check a synchronized call into native code.
+ */
+void dvmCheckCallSynchronizedJNIMethod(const u4* args, JValue* pResult,
+    const Method* method, Thread* self)
+{
+    dvmCallSynchronizedJNIMethod(args, pResult, method, self);
+    if (method->shorty[0] == 'L' && !dvmCheckException(self) &&
+        pResult->l != NULL)
+    {
+        checkCallCommon(args, pResult, method, self);
+    }
+}
+
+
+/*
+ * ===========================================================================
+ *      JNI function helpers
+ * ===========================================================================
+ */
+
 #define JNI_ENTER()     dvmChangeStatus(NULL, THREAD_RUNNING)
 #define JNI_EXIT()      dvmChangeStatus(NULL, THREAD_NATIVE)
 
@@ -145,7 +255,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) {
@@ -1308,7 +1418,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 +1431,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,   \
@@ -1353,7 +1463,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 +1475,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,          \
@@ -1396,8 +1506,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 +1546,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 +1601,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 +1653,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)
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..26b52be 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         16
 
 #endif /*_DALVIK_VERSION*/
diff --git a/vm/Dvm.mk b/vm/Dvm.mk
new file mode 100644
index 0000000..1280c17
--- /dev/null
+++ b/vm/Dvm.mk
@@ -0,0 +1,332 @@
+# 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
+
+#
+# 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 += -DWITH_EXTRA_GC_CHECKS=1
+  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 \
+	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
+endif
+
+ifeq ($(WITH_JIT),true)
+  # NOTE: Turn on assertion for JIT for now
+  LOCAL_CFLAGS += -DWITH_DALVIK_ASSERT
+  # NOTE: Also turn on tuning when JIT is enabled for now
+  LOCAL_CFLAGS += -DWITH_JIT_TUNING
+  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..2ac1187 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;
@@ -338,6 +342,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 +371,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:
      *
@@ -417,12 +429,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 +498,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;
 
     /*
@@ -612,8 +626,121 @@
 #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..0106fe4
--- /dev/null
+++ b/vm/IndirectRefTable.c
@@ -0,0 +1,453 @@
+/*
+ * 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_SEGMENT_INIT;
+    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("ReferenceTable 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 entries)\n",
+                pRef->allocEntries, newSize);
+            return false;
+        }
+        LOGI("Growing %p from %d to %d\n", pRef, pRef->allocEntries, newSize);
+
+        /* 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)
+{
+    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..4c842f2
--- /dev/null
+++ b/vm/IndirectRefTable.h
@@ -0,0 +1,344 @@
+/*
+ * 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.)
+ *
+ * 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.
+ */
+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;
+
+/* initial value to use for the "cookie" */
+#define IRT_SEGMENT_INIT    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;
+}
+
+/*
+ * 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..4a2033e 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;
+            LOGD("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,14 @@
         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 signal handling */
     if (!gDvm.reduceSignals)
         blockSignals();
@@ -957,6 +1138,8 @@
         goto fail;
     if (!dvmVerificationStartup())
         goto fail;
+    if (!dvmRegisterMapStartup())
+        goto fail;
     if (!dvmInstanceofStartup())
         goto fail;
     if (!dvmClassStartup())
@@ -1028,7 +1211,7 @@
      * Do some "late" initialization for the memory allocator.  This may
      * allocate storage and initialize classes.
      */
-    if (!dvmGcLateInit())
+    if (!dvmCreateStockExceptions())
         goto fail;
 
     /*
@@ -1058,7 +1241,10 @@
 
 
 #ifndef NDEBUG
-    dvmTestHash();
+    if (!dvmTestHash())
+        LOGE("dmvTestHash FAILED\n");
+    if (false /*noisy!*/ && !dvmTestIndirectRefTable())
+        LOGE("dvmTestIndirectRefTable FAILED\n");
 #endif
 
     assert(!dvmCheckException(dvmThreadSelf()));
@@ -1167,6 +1353,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 +1481,8 @@
         goto fail;
     if (!dvmVerificationStartup())
         goto fail;
+    if (!dvmRegisterMapStartup())
+        goto fail;
     if (!dvmInstanceofStartup())
         goto fail;
     if (!dvmClassStartup())
@@ -1350,6 +1543,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 +1568,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..9871d4e 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.
  */
@@ -953,14 +954,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 +965,34 @@
 }
 
 /*
+ * 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)
+{
+    if (dvmIsCheckJNIEnabled()) {
+        if (dvmIsSynchronizedMethod(method))
+            dvmSetNativeFunc(method, dvmCheckCallSynchronizedJNIMethod, func);
+        else
+            dvmSetNativeFunc(method, dvmCheckCallJNIMethod, func);
+    } else {
+        if (dvmIsSynchronizedMethod(method))
+            dvmSetNativeFunc(method, dvmCallSynchronizedJNIMethod, func);
+        else
+            dvmSetNativeFunc(method, dvmCallJNIMethod, func);
+    }
+}
+
+/*
  * Get the method currently being executed by examining the interp stack.
  */
 const Method* dvmGetCurrentJNIMethod(void)
@@ -2747,7 +2769,7 @@
 {
     JNI_ENTER();
     jobjectRefType type;
-    
+
     if (obj == NULL)
         type = JNIInvalidRefType;
     else
@@ -3438,6 +3460,10 @@
 /*
  * 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)
 {
diff --git a/vm/JniInternal.h b/vm/JniInternal.h
index 79d16ec..df3ca54 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
@@ -115,11 +120,23 @@
 
 /*
  * JNI call bridges.  Not usually 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,
     const Method* method, Thread* self);
+void dvmCheckCallJNIMethod(const u4* args, JValue* pResult,
+    const Method* method, Thread* self);
+void dvmCheckCallSynchronizedJNIMethod(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.
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..6b1372c 100644
--- a/vm/Misc.c
+++ b/vm/Misc.c
@@ -297,6 +297,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 +343,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..1566161 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,15 @@
  */
 bool dvmSetCloseOnExec(int fd);
 
+/*
+ * Unconditionally abort the entire VM.  Try not to use this.
+ */
+void dvmAbort(void)
+#if defined(__GNUC__)
+    __attribute__ ((noreturn))
+#endif
+    ;
+
 #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..1892618 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,10 +112,8 @@
     /* 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);
+        /* found it, point it at the JNI bridge and then call it */
+        dvmUseJNIBridge((Method*) method, func);
         dvmCallJNIMethod(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..7758660 100644
--- a/vm/Properties.c
+++ b/vm/Properties.c
@@ -186,9 +186,11 @@
     setProperty(propObj, put, "java.specification.version", "0.9");
 
     #define OS_ARCH generic /* TODO: Use an "arch" header. */
-    #define OS_ARCH_QUOTE(x) #x
+    #define OS_ARCH_QUOTE1(x) #x
+    #define OS_ARCH_QUOTE(x) OS_ARCH_QUOTE1(x)
     setProperty(propObj, put, "os.arch", OS_ARCH_QUOTE(OS_ARCH));
     #undef OS_ARCH
+    #undef OS_ARCH_QUOTE1
     #undef OS_ARCH_QUOTE
 
     setProperty(propObj, put, "os.name", info.sysname);
diff --git a/vm/ReferenceTable.c b/vm/ReferenceTable.c
index c748222..089f2f2 100644
--- a/vm/ReferenceTable.c
+++ b/vm/ReferenceTable.c
@@ -58,11 +58,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;
 
diff --git a/vm/SignalCatcher.c b/vm/SignalCatcher.c
index 550f777..309ad5d 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,6 +240,10 @@
 
             logThreadStacks();
 
+#if defined(WITH_JIT) && defined(WITH_JIT_TUNING)
+            dvmCompilerDumpStats();
+#endif
+
             if (false) {
                 dvmLockMutex(&gDvm.jniGlobalRefLock);
                 dvmDumpReferenceTable(&gDvm.jniGlobalRefTable, "JNI global");
@@ -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..e0f986d 100644
--- a/vm/Thread.c
+++ b/vm/Thread.c
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 /*
  * Thread support.
  */
@@ -26,6 +27,7 @@
 #include <sys/resource.h>
 #include <sys/mman.h>
 #include <errno.h>
+#include <fcntl.h>
 
 #if defined(HAVE_PRCTL)
 #include <sys/prctl.h>
@@ -233,6 +235,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 +410,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 +464,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 +481,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
     }
@@ -519,8 +540,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 +601,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 +629,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);
 }
 
 
@@ -995,6 +1089,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 +1104,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();
     }
@@ -1470,7 +1569,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 +1661,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);
 }
 
@@ -2138,7 +2243,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 +2272,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 +2310,7 @@
      * though.
      */
     lockThreadSuspendCount();
-    self->suspendCount++;
+    dvmAddToThreadSuspendCount(&self->suspendCount, 1);
     self->dbgSuspendCount++;
 
     /*
@@ -2343,29 +2448,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 +2536,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 +2614,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++;
     }
@@ -2521,7 +2691,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 +2782,8 @@
         }
 
         assert(thread->suspendCount >= thread->dbgSuspendCount);
-        thread->suspendCount -= thread->dbgSuspendCount;
+        dvmAddToThreadSuspendCount(&thread->suspendCount,
+                                   -thread->dbgSuspendCount);
         thread->dbgSuspendCount = 0;
     }
     unlockThreadSuspendCount();
@@ -2827,6 +2998,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,35 +3039,40 @@
 };
 
 /*
- * Change the scheduler cgroup of a pid
+ * Change the scheduler cgroup of the current thread.
+ *
+ * Returns 0 on success.
  */
 int dvmChangeThreadSchedulerGroup(const char *cgroup)
 {
 #ifdef HAVE_ANDROID_OS
-    FILE *fp;
+    int fd;
     char path[255];
-    int rc;
 
-    sprintf(path, "/dev/cpuctl/%s/tasks", (cgroup ? cgroup : ""));
+    snprintf(path, sizeof(path), "/dev/cpuctl/%s/tasks", (cgroup ? cgroup :""));
 
-    if (!(fp = fopen(path, "w"))) {
+    if ((fd = open(path, O_WRONLY)) < 0) {
+        int err = errno;
 #if ENABLE_CGROUP_ERR_LOGGING
-        LOGW("Unable to open %s (%s)\n", path, strerror(errno));
+        LOGW("Unable to open %s (%s)\n", path, strerror(err));
 #endif
-        return -errno;
+        return -err;
     }
 
-    rc = fprintf(fp, "0");
-    fclose(fp);
-
-    if (rc < 0) {
+    if (write(fd, "0", 1) < 0) {
+        int err = errno;
 #if ENABLE_CGROUP_ERR_LOGGING
-        LOGW("Unable to move pid %d to cgroup %s (%s)\n", getpid(),
-             (cgroup ? cgroup : "<default>"), strerror(errno));
+        LOGW("Unable to move tid %d to cgroup %s (%s)\n",
+            dvmThreadSelf()->systemTid,
+            (cgroup ? cgroup : "<default>"), strerror(err));
 #endif
+        close(fd);
+        return -err;
     }
+    close(fd);
 
-    return (rc < 0) ? errno : 0;
+    return 0;
+
 #else // HAVE_ANDROID_OS
     return 0;
 #endif
@@ -2902,7 +3095,7 @@
     }
     newNice = kNiceValues[newPriority-1];
 
-    if (newPriority >= ANDROID_PRIORITY_BACKGROUND) {
+    if (newNice >= ANDROID_PRIORITY_BACKGROUND) {
         dvmChangeThreadSchedulerGroup("bg_non_interactive");
     } else if (getpriority(PRIO_PROCESS, pid) >= ANDROID_PRIORITY_BACKGROUND) {
         dvmChangeThreadSchedulerGroup(NULL);
@@ -2981,6 +3174,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 +3243,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 +3266,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 +3299,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 +3524,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 +3541,185 @@
 
         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.
+                 *
+                 * TODO: we should be able to remove this for production --
+                 * no need to keep banging on the global.
+                 */
+                if (gDvm.preciseGc) {
+                    LOGV("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 ||
@@ -3410,4 +3824,3 @@
      */
     gcScanAllThreads();
 }
-
diff --git a/vm/Thread.h b/vm/Thread.h
index 9c15f9e..45018b4 100644
--- a/vm/Thread.h
+++ b/vm/Thread.h
@@ -151,6 +151,7 @@
     ReferenceTable  internalLocalRefTable;
 
     /* JNI local reference tracking */
+    // TODO: move this to JNIEnvExt to avoid an indirection?
     ReferenceTable  jniLocalRefTable;
 
     /* JNI native monitor reference tracking (initialized on first use) */
@@ -203,6 +204,11 @@
 #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
 } Thread;
 
 /* start point for an internal thread; mimics pthread args */
@@ -250,6 +256,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 +286,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);
 }
 
 /*
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..f1156d3 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..c548190 100644
--- a/vm/alloc/Heap.c
+++ b/vm/alloc/Heap.c
@@ -148,15 +148,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 +180,7 @@
         if (self != NULL) {
             oldStatus = dvmChangeStatus(self, THREAD_VMWAIT);
         } else {
+            LOGI("ODD: waiting on heap lock, no self\n");
             oldStatus = -1; // shut up gcc
         }
 
@@ -867,7 +874,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.
      */
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..a1862bb 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,121 @@
 
 
 /*
+ * 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)
+{
+    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:
+
+    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:
+
+    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:
+        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);
+
+    result = true;
+
+bail:
+    dvmMakeCodeReadOnly(meth);
+    return result;
+}
+
+
+/*
  * ===========================================================================
  *      Entry point and driver loop
  * ===========================================================================
@@ -2779,7 +3041,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 +3068,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 +3195,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 +3353,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 +3426,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 +3467,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 +3502,7 @@
          */
         if (decInsn.vA != 0) {
             LOG_VFY("VFY: encountered data table in instruction stream\n");
-            okay = false;
+            failure = VERIFY_ERROR_GENERIC;
         }
         break;
 
@@ -3237,18 +3510,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 +3537,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 +3557,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 +3648,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 +3670,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 +3683,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 +3727,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 +3823,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 +3874,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 +3920,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 +3931,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 +3945,7 @@
             {
                 LOG_VFY("VFY: invalid fill-array-data on %s\n",
                         resClass->descriptor);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
 
@@ -3678,7 +3960,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 +3994,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 +4005,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 +4017,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 +4029,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 +4089,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 +4105,7 @@
                 {
                     LOG_VFY("VFY: invalid aget-1nr target %s\n",
                         resClass->descriptor);
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
 
@@ -3833,13 +4117,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 +4132,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 +4148,7 @@
                 {
                     LOG_VFY("VFY: invalid aget-wide target %s\n",
                         resClass->descriptor);
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
 
@@ -3880,7 +4164,7 @@
                     LOG_VFY("VFY: invalid aget-wide on %s\n",
                         resClass->descriptor);
                     dstType = kRegTypeUnknown;
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
             } else {
@@ -3893,7 +4177,7 @@
                 dstType = kRegTypeLongLo;
             }
             setRegisterType(workRegs, insnRegCount, decInsn.vA,
-                dstType, &okay);
+                dstType, &failure);
         }
         break;
 
@@ -3902,15 +4186,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 +4202,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 +4222,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 +4238,7 @@
                 dstType = kRegTypeZero;
             }
             setRegisterType(workRegs, insnRegCount, decInsn.vA,
-                dstType, &okay);
+                dstType, &failure);
         }
         break;
     case OP_APUT:
@@ -3977,24 +4261,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 +4289,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 +4301,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 +4334,7 @@
             {
                 LOG_VFY("VFY: invalid aput-wide on %s\n",
                         resClass->descriptor);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
 
@@ -4062,22 +4346,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 +4373,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 +4405,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 +4434,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 +4450,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 +4466,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 +4486,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 +4502,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 +4545,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 +4583,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 +4623,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 +4636,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 +4671,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 +4682,7 @@
                             valueClass->descriptor, fieldClass->descriptor,
                             instField->field.clazz->descriptor,
                             instField->field.name);
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
             }
@@ -4416,8 +4709,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 +4726,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 +4739,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 +4755,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 +4769,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 +4808,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 +4845,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 +4878,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 +4890,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 +4921,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 +4932,7 @@
                             valueClass->descriptor, fieldClass->descriptor,
                             staticField->field.clazz->descriptor,
                             staticField->field.name);
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
             }
@@ -4654,11 +4956,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 +4974,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 +4990,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 +5011,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 +5036,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 +5056,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 +5075,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 +5086,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 +5098,7 @@
                 thisClass = regTypeInitializedReferenceToClass(thisType);
                 if (thisClass == NULL) {
                     LOG_VFY("VFY: interface call on uninitialized\n");
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
 
@@ -4812,7 +5114,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 +5126,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 +5134,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 +5219,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 +5236,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 +5251,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 +5259,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 +5270,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 +5291,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 +5305,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 +5313,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 +5322,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 +5336,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 +5410,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 +5433,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 +5448,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 +5544,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 +5636,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..8ae2af5 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,25 @@
 };
 
 /*
+ * 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 (ref=class) */
+    VERIFY_ERROR_NO_FIELD,      /* NoSuchFieldError (ref=field) */
+    VERIFY_ERROR_NO_METHOD,     /* NoSuchMethodError (ref=method) */
+    VERIFY_ERROR_ACCESS_CLASS,  /* IllegalAccessError (ref=class) */
+    VERIFY_ERROR_ACCESS_FIELD,  /* IllegalAccessError (ref=field) */
+    VERIFY_ERROR_ACCESS_METHOD, /* IllegalAccessError (ref=method) */
+    VERIFY_ERROR_CLASS_CHANGE,  /* IncompatibleClassChangeError (ref=class) */
+    VERIFY_ERROR_INSTANTIATION, /* InstantiationError (ref=class) */
+} VerifyError;
+
+#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 +101,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..ad843d0 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,1828 @@
 #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     true
+
+/* 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 1
+    if (!verifyMap(vdata, pMap))
+        goto bail;
+#endif
+#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 +1899,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.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..6cb680c 100644
--- a/vm/arch/x86/Call386ABI.S
+++ b/vm/arch/x86/Call386ABI.S
@@ -131,12 +131,31 @@
     /* 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,%eax  /* U2? */
+    jne      isSignedShort
+    movzwl   %ax,%eax
+    movl     %eax,(%ecx)
+    jmp      cleanUpAndExit
+isSignedShort:
+    /* Must be S2 */
+    movswl   %ax,%eax
+    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..5e59991
--- /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_nextEntry] @ r9<- thread->refNext
+    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
+    str     r9, [r1, #(offStackSaveArea_localRefTop - sizeofStackSaveArea)]
+                                        @ newFp->localRefTop=refNext
+    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_localRefTop] @ r0<- newSave->localRefTop
+    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
+    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..29073c3
--- /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_nextEntry] @ r9<- thread->refNext
+    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
+    str     r9, [r1, #(offStackSaveArea_localRefTop - sizeofStackSaveArea)]
+                                        @ newFp->localRefTop=refNext
+    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_localRefTop] @ r0<- newSave->localRefTop
+    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
+    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..2c669f8
--- /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_nextEntry] @ r9<- thread->refNext
+    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
+    str     r9, [r1, #(offStackSaveArea_localRefTop - sizeofStackSaveArea)]
+                                        @ newFp->localRefTop=refNext
+    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_localRefTop] @ r0<- newSave->localRefTop
+    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
+    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_nextEntry] @ r9<- thread->refNext
+    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
+    str     r9, [r1, #(offStackSaveArea_localRefTop - sizeofStackSaveArea)]
+                                        @ newFp->localRefTop=refNext
+    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_localRefTop] @ r0<- newSave->localRefTop
+    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
+    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..b973691
--- /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_nextEntry] @ r9<- thread->refNext
+    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
+    str     r9, [r1, #(offStackSaveArea_localRefTop - sizeofStackSaveArea)]
+                                        @ newFp->localRefTop=refNext
+    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_localRefTop] @ r0<- newSave->localRefTop
+    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
+    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_nextEntry] @ r9<- thread->refNext
+    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
+    str     r9, [r1, #(offStackSaveArea_localRefTop - sizeofStackSaveArea)]
+                                        @ newFp->localRefTop=refNext
+    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_localRefTop] @ r0<- newSave->localRefTop
+    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
+    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..1faf7f6
--- /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_nextEntry] @ r9<- thread->refNext
+    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
+    str     r9, [r1, #(offStackSaveArea_localRefTop - sizeofStackSaveArea)]
+                                        @ newFp->localRefTop=refNext
+    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_localRefTop] @ r0<- newSave->localRefTop
+    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
+    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_nextEntry] @ r9<- thread->refNext
+    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
+    str     r9, [r1, #(offStackSaveArea_localRefTop - sizeofStackSaveArea)]
+                                        @ newFp->localRefTop=refNext
+    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_localRefTop] @ r0<- newSave->localRefTop
+    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
+    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..f45e21a 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,160 @@
 }
 
 
+
+/*
+ * Helpers for dvmThrowVerificationError().
+ *
+ * Each returns a newly-allocated string.
+ */
+#define kThrowShow_accessFromClass     1
+static char* classNameFromIndex(const Method* method, int ref, int flags)
+{
+    static const int kBufLen = 256;
+    const DvmDex* pDvmDex = method->clazz->pDvmDex;
+    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, int flags)
+{
+    static const int kBufLen = 256;
+    const DvmDex* pDvmDex = method->clazz->pDvmDex;
+    const DexFieldId* pFieldId;
+    const char* className;
+    const char* fieldName;
+
+    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, int flags)
+{
+    static const int kBufLen = 384;
+    const DvmDex* pDvmDex = method->clazz->pDvmDex;
+    const DexMethodId* pMethodId;
+    const char* className;
+    const char* methodName;
+
+    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.  The
+ * meaning of "ref" is kind-specific; it's usually an index to a
+ * class, field, or method reference.
+ */
+void dvmThrowVerificationError(const Method* method, int kind, int ref)
+{
+    const char* exceptionName = "Ljava/lang/VerifyError;";
+    char* msg = NULL;
+
+    switch ((VerifyError) kind) {
+    case VERIFY_ERROR_NO_CLASS:
+        exceptionName = "Ljava/lang/NoClassDefFoundError;";
+        msg = classNameFromIndex(method, ref, 0);
+        break;
+    case VERIFY_ERROR_NO_FIELD:
+        exceptionName = "Ljava/lang/NoSuchFieldError;";
+        msg = fieldNameFromIndex(method, ref, 0);
+        break;
+    case VERIFY_ERROR_NO_METHOD:
+        exceptionName = "Ljava/lang/NoSuchMethodError;";
+        msg = methodNameFromIndex(method, ref, 0);
+        break;
+    case VERIFY_ERROR_ACCESS_CLASS:
+        exceptionName = "Ljava/lang/IllegalAccessError;";
+        msg = classNameFromIndex(method, ref, kThrowShow_accessFromClass);
+        break;
+    case VERIFY_ERROR_ACCESS_FIELD:
+        exceptionName = "Ljava/lang/IllegalAccessError;";
+        msg = fieldNameFromIndex(method, ref, kThrowShow_accessFromClass);
+        break;
+    case VERIFY_ERROR_ACCESS_METHOD:
+        exceptionName = "Ljava/lang/IllegalAccessError;";
+        msg = methodNameFromIndex(method, ref, kThrowShow_accessFromClass);
+        break;
+    case VERIFY_ERROR_CLASS_CHANGE:
+        exceptionName = "Ljava/lang/IncompatibleClassChangeError;";
+        msg = classNameFromIndex(method, ref, 0);
+        break;
+    case VERIFY_ERROR_INSTANTIATION:
+        exceptionName = "Ljava/lang/InstantiationError;";
+        msg = classNameFromIndex(method, ref, 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 +860,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 +891,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 +939,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 +957,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 +970,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..969bea9 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;
@@ -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;
@@ -217,9 +219,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;
@@ -505,11 +508,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);
     }
@@ -611,11 +620,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 +730,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);
     }
diff --git a/vm/interp/Stack.h b/vm/interp/Stack.h
index 1b28d49..f2a481b 100644
--- a/vm/interp/Stack.h
+++ b/vm/interp/Stack.h
@@ -146,6 +146,8 @@
         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
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..004ee13 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,19 +400,31 @@
     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
@@ -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..5997c35 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,7 +857,7 @@
             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 {
@@ -876,7 +879,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 +916,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 +932,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..716df3d 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)
@@ -131,14 +155,16 @@
 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_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_returnAddr, StackSaveArea, returnAddr, 16)
+MTERP_SIZEOF(sizeofStackSaveArea,       StackSaveArea, 20)
 #endif
 
 /* InstField fields */
@@ -200,6 +226,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 +264,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..b0aa69b 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,19 +9872,31 @@
     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
@@ -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..5a8ae4c
--- /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_nextEntry] @ r9<- thread->refNext
+    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
+    str     r9, [r10, #offStackSaveArea_localRefTop] @newFp->localRefTop=refNext
+    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_localRefTop] @ r0<- newSave->localRefTop
+    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
+    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..3f2069c 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,19 +9866,31 @@
     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
@@ -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..0555a30
--- /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_nextEntry] @ r9<- thread->refNext
+    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
+    str     r9, [r10, #offStackSaveArea_localRefTop] @newFp->localRefTop=refNext
+    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_localRefTop] @ r0<- newSave->localRefTop
+    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
+    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..52007b0 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_nextEntry(%ecx), %eax # %eax<- glue->self->thread->refNext
+    movl        %eax, offStackSaveArea_localRefTop(%edx) # newSaveArea->localRefTop<- refNext
+    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_localRefTop(%ecx), %edx # %edx<- newSaveArea->localRefTop
+    cmp         $0, offThread_exception(%eax) # check for exception
+    movl        rFP, offThread_curFrame(%eax) # glue->self->curFrame<- rFP
+    movl        %edx, offThread_jniLocal_nextEntry(%eax) # glue->self<- newSaveArea->localRefTop
+    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..bb1d0ea 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,7 +3890,7 @@
             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 {
@@ -3901,7 +3912,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 +3949,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 +3966,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..90b2a75 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,7 +4181,7 @@
             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 {
@@ -4162,7 +4203,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 +4240,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 +4257,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..c28bf5b 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,7 +3895,7 @@
             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 {
@@ -3882,7 +3917,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 +3954,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 +3971,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..9bb70d1 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,7 +2045,7 @@
             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 {
@@ -2051,7 +2067,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 +2104,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 +2121,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..d86207a 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_nextEntry(%ecx), %eax # %eax<- glue->self->thread->refNext
+    movl        %eax, offStackSaveArea_localRefTop(%edx) # newSaveArea->localRefTop<- refNext
+    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_localRefTop(%ecx), %edx # %edx<- newSaveArea->localRefTop
+    cmp         $$0, offThread_exception(%eax) # check for exception
+    movl        rFP, offThread_curFrame(%eax) # glue->self->curFrame<- rFP
+    movl        %edx, offThread_jniLocal_nextEntry(%eax) # glue->self<- newSaveArea->localRefTop
+    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/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..13f4f46
--- /dev/null
+++ b/vm/native/dalvik_system_SamplingProfiler.c
@@ -0,0 +1,615 @@
+/*
+ * 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"
+
+// ~16k
+#define INITIAL_CAPACITY 1024
+
+// ~64k
+#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,
+    /** In a native method. */
+    NATIVE_THREAD,
+    /** Waiting on a lock or VM resource. */
+    SUSPENDED_THREAD
+} ThreadState;
+
+#define THREAD_STATE_SIZE (SUSPENDED_THREAD + 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]; // 12 bytes
+} 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) {
+    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]++;
+            return;
+        }
+
+        if (entry->method == NULL) {
+            // Add a new entry.
+            if (set->size < set->maxSize) {
+                entry->method = method;
+                entry->counts[threadType][threadState] = 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);
+                } 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 (thread->status) {
+        case THREAD_RUNNING: threadState = RUNNING_THREAD; break;
+        case THREAD_NATIVE: threadState = NATIVE_THREAD; break;
+        default: threadState = SUSPENDED_THREAD;
+    }
+
+    /*
+     * 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;
+    }
+
+    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);
+        }
+
+        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(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;
+        size += THREAD_TYPE_SIZE * THREAD_STATE_SIZE * 2; // sample counts
+        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] = wrapper->methodCount->counts;
+        int type, state;
+        for (type = 0; type < THREAD_TYPE_SIZE; type++)
+            for (state = 0; state < THREAD_STATE_SIZE; state++)
+                writeShort(offset, counts[type][state]);
+
+        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
+     *    Counts (for event thread)
+     *    Counts (for other threads)
+     *
+     *  Counts:
+     *    running count (2 bytes)
+     *    native count (2 bytes)
+     *    suspended count (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];
+        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);
+}
+
+/**
+ * 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 },
+    { "allocate", "()I", Dalvik_dalvik_system_SamplingProfiler_allocate },
+    { "setEventThread", "(ILjava/lang/Thread;)V",
+            Dalvik_dalvik_system_SamplingProfiler_setEventThread },
+    { NULL, NULL, NULL },
+};
\ No newline at end of file
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..50ef961 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 >= 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..72f8f33
--- /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_SEGMENT_INIT;
+    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_SEGMENT_INIT;
+    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*/