changeset 13391:966f8b2c8cd3

Merge
author prr
date Tue, 22 Dec 2015 09:14:16 -0800
parents d5a55d89a3bd 724df36317cc
children 17c65015ebcc
files src/java.base/share/classes/sun/misc/BASE64Decoder.java src/java.base/share/classes/sun/misc/BASE64Encoder.java src/java.base/share/classes/sun/misc/CharacterDecoder.java src/java.base/share/classes/sun/misc/CharacterEncoder.java src/java.base/share/classes/sun/misc/DoubleConsts.java src/java.base/share/classes/sun/misc/FDBigInteger.java src/java.base/share/classes/sun/misc/FloatConsts.java src/java.base/share/classes/sun/misc/FloatingDecimal.java src/java.base/share/classes/sun/misc/FormattedFloatingDecimal.java src/java.base/share/classes/sun/misc/ProxyGenerator.java src/java.base/share/classes/sun/misc/Queue.java src/java.base/share/classes/sun/misc/UCDecoder.java src/java.base/share/classes/sun/misc/UCEncoder.java src/java.base/share/classes/sun/misc/UUDecoder.java src/java.base/share/classes/sun/misc/UUEncoder.java test/ProblemList.txt test/sun/misc/Encode/DecodeBuffer.java test/sun/misc/Encode/Encode.java test/sun/misc/Encode/GetBytes.java test/sun/misc/FloatingDecimal/OldFDBigIntForTest.java test/sun/misc/FloatingDecimal/OldFloatingDecimalForTest.java test/sun/misc/FloatingDecimal/TestFDBigInteger.java test/sun/misc/FloatingDecimal/TestFloatingDecimal.java
diffstat 217 files changed, 14985 insertions(+), 13255 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Mon Dec 14 14:12:17 2015 -0800
+++ b/.hgtags	Tue Dec 22 09:14:16 2015 -0800
@@ -339,3 +339,5 @@
 559b626b01179420a94feb9c3d0f246970d2e3fa jdk9-b94
 8581faf0d474472e32f589bbc16db7eec912d83f jdk-9+95
 c021b855f51e572e63982654b17742cb1f814fb4 jdk-9+96
+fdd84b2265ddce7f50e084b7c8635189bba6f012 jdk-9+97
+f86ee68d1107dad41a27efc34306e0e56244a12e jdk-9+98
--- a/make/CompileDemos.gmk	Mon Dec 14 14:12:17 2015 -0800
+++ b/make/CompileDemos.gmk	Tue Dec 22 09:14:16 2015 -0800
@@ -309,7 +309,7 @@
 
   ifeq ($$($1_TOOLCHAIN), TOOLCHAIN_LINK_CXX)
     # For C++, we also need some special treatment.
-    $1_LDFLAGS := $(LDFLAGS_CXX_JDK)
+    $1_LDFLAGS := $$(LDFLAGS_CXX_JDK)
     $1_LIBS := $(LIBCXX)
 
     ifeq ($(OPENJDK_TARGET_CPU_ARCH), sparc)
@@ -324,9 +324,9 @@
       OPTIMIZATION := LOW, \
       CFLAGS := $$($1_CFLAGS_INCLUDE) $$(CFLAGS_JDKLIB) $$(CFLAGS_DEBUG_SYMBOLS), \
       CXXFLAGS := $$($1_CXXFLAGS), \
-      LDFLAGS := $(filter-out -incremental:no -opt:ref, $(LDFLAGS_JDKLIB)) \
+      LDFLAGS := $(filter-out -incremental:no -opt:ref, $$(LDFLAGS_JDKLIB)) \
           $$($1_LDFLAGS), \
-      LDFLAGS_macosx := $(call SET_EXECUTABLE_ORIGIN), \
+      LDFLAGS_macosx := $$(call SET_EXECUTABLE_ORIGIN), \
       LIBS := $$($1_LIBS), \
       LIBS_solaris := -lc, \
       VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \
--- a/make/launcher/Launcher-java.base.gmk	Mon Dec 14 14:12:17 2015 -0800
+++ b/make/launcher/Launcher-java.base.gmk	Tue Dec 22 09:14:16 2015 -0800
@@ -127,8 +127,7 @@
           $(BUILD_JEXEC_INC), \
       CFLAGS_linux := -fPIC, \
       CFLAGS_solaris := -KPIC, \
-      LDFLAGS := $(LDFLAGS_JDKEXE) \
-          $(call SET_SHARED_LIBRARY_NAME,$(LIBRARY_PREFIX)$(SHARED_LIBRARY_SUFFIX)), \
+      LDFLAGS := $(LDFLAGS_JDKEXE), \
       OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/jexec_obj, \
       OUTPUT_DIR := $(BUILD_JEXEC_DST_DIR), \
       DEBUG_SYMBOLS := true, \
--- a/make/launcher/Launcher-jdk.pack200.gmk	Mon Dec 14 14:12:17 2015 -0800
+++ b/make/launcher/Launcher-jdk.pack200.gmk	Tue Dec 22 09:14:16 2015 -0800
@@ -89,7 +89,6 @@
     MAPFILE := $(UNPACK_MAPFILE),\
     LDFLAGS := $(UNPACKEXE_ZIPOBJS) \
         $(LDFLAGS_JDKEXE) $(LDFLAGS_CXX_JDK) \
-        $(call SET_SHARED_LIBRARY_NAME,$(LIBRARY_PREFIX)unpack$(SHARED_LIBRARY_SUFFIX)) \
         $(call SET_SHARED_LIBRARY_ORIGIN), \
     LIBS := $(UNPACKEXE_LIBS) $(LIBCXX), \
     LIBS_solaris :=  -lc, \
--- a/make/launcher/LauncherCommon.gmk	Mon Dec 14 14:12:17 2015 -0800
+++ b/make/launcher/LauncherCommon.gmk	Tue Dec 22 09:14:16 2015 -0800
@@ -25,6 +25,12 @@
 
 include NativeCompilation.gmk
 
+# SetupNativeCompilation now supports debug symbols on macosx for hotspot.
+# Disable it here for the jdk binaries until we decide to enable them.
+ifeq ($(OPENJDK_TARGET_OS), macosx)
+  ENABLE_DEBUG_SYMBOLS := false
+endif
+
 # Prepare the find cache.
 $(eval $(call FillCacheFind, $(JDK_TOPDIR)/src/java.base/share/native/launcher))
 
@@ -180,15 +186,12 @@
       CFLAGS_linux := -fPIC, \
       CFLAGS_solaris := -KPIC -DHAVE_GETHRTIME, \
       CFLAGS_windows := $$($1_CFLAGS_windows), \
-      LDFLAGS := $(LDFLAGS_JDKEXE) \
+      LDFLAGS := $$(LDFLAGS_JDKEXE) \
           $$(ORIGIN_ARG) \
           $$($1_LDFLAGS), \
       LDFLAGS_linux := \
-          $(call SET_SHARED_LIBRARY_NAME,$(LIBRARY_PREFIX)$(SHARED_LIBRARY_SUFFIX)) \
           -L$(SUPPORT_OUTPUTDIR)/modules_libs/java.base$(OPENJDK_TARGET_CPU_LIBDIR)/jli, \
-      LDFLAGS_macosx := $(call SET_SHARED_LIBRARY_NAME,$1), \
       LDFLAGS_solaris := $$($1_LDFLAGS_solaris) \
-          $(call SET_SHARED_LIBRARY_NAME,$(LIBRARY_PREFIX)$(SHARED_LIBRARY_SUFFIX)) \
           -L$(SUPPORT_OUTPUTDIR)/modules_libs/java.base$(OPENJDK_TARGET_CPU_LIBDIR)/jli, \
       MAPFILE := $$($1_MAPFILE), \
       LIBS := $(JDKEXE_LIBS) $$($1_LIBS), \
--- a/make/lib/Awt2dLibraries.gmk	Mon Dec 14 14:12:17 2015 -0800
+++ b/make/lib/Awt2dLibraries.gmk	Tue Dec 22 09:14:16 2015 -0800
@@ -683,7 +683,7 @@
     WARNINGS_AS_ERRORS_gcc := false, \
     WARNINGS_AS_ERRORS_solstudio := false, \
     MAPFILE := $(BUILD_LIBFONTMANAGER_MAPFILE), \
-    LDFLAGS := $(subst -Xlinker -z -Xlinker defs,,$(LDFLAGS_JDKLIB)) $(LDFLAGS_CXX_JDK) \
+    LDFLAGS := $(subst -Wl$(COMMA)-z$(COMMA)defs,,$(LDFLAGS_JDKLIB)) $(LDFLAGS_CXX_JDK) \
         $(call SET_SHARED_LIBRARY_ORIGIN), \
     LDFLAGS_unix := -L$(INSTALL_LIBRARIES_HERE), \
     LDFLAGS_macosx := -undefined dynamic_lookup, \
@@ -799,7 +799,7 @@
       LDFLAGS := $(LDFLAGS_JDKLIB) \
           $(call SET_SHARED_LIBRARY_ORIGIN), \
       LDFLAGS_unix := -L$(INSTALL_LIBRARIES_HERE), \
-      LDFLAGS_macosx := -Xlinker -rpath -Xlinker @loader_path, \
+      LDFLAGS_macosx := -Wl$(COMMA)-rpath$(COMMA)@loader_path, \
       LIBS_unix := $(JAWT_LIBS) $(JDKLIB_LIBS), \
       LIBS_solaris := $(X_LIBS) -lXrender, \
       LIBS_macosx := -framework Cocoa, \
@@ -1034,7 +1034,7 @@
           -I$(SUPPORT_OUTPUTDIR)/headers/java.desktop,  \
       LDFLAGS := $(LDFLAGS_JDKLIB) \
           $(call SET_SHARED_LIBRARY_ORIGIN) \
-          -Xlinker -rpath -Xlinker @loader_path \
+          -Wl$(COMMA)-rpath$(COMMA)@loader_path \
           -L$(INSTALL_LIBRARIES_HERE), \
       LIBS := -lawt -losxapp -lawt_lwawt \
           -framework Cocoa \
--- a/make/lib/Lib-java.instrument.gmk	Mon Dec 14 14:12:17 2015 -0800
+++ b/make/lib/Lib-java.instrument.gmk	Tue Dec 22 09:14:16 2015 -0800
@@ -65,7 +65,7 @@
         -L$(call FindLibDirForModule, java.base)/jli, \
     LDFLAGS_solaris := $(call SET_SHARED_LIBRARY_ORIGIN,/jli) \
         -L$(call FindLibDirForModule, java.base)/jli, \
-    LDFLAGS_macosx := -Xlinker -all_load $(SUPPORT_OUTPUTDIR)/native/java.base/libjli_static.a, \
+    LDFLAGS_macosx := -Wl$(COMMA)-all_load, \
     LDFLAGS_aix := -L$(SUPPORT_OUTPUTDIR)/native/java.base, \
     LDFLAGS_windows := -export:Agent_OnAttach, \
     LIBS := $(JDKLIB_LIBS), \
@@ -74,7 +74,8 @@
     LIBS_solaris := -ljli $(LIBDL), \
     LIBS_aix := -liconv -ljli_static $(LIBDL), \
     LIBS_macosx := -liconv -framework Cocoa -framework Security \
-        -framework ApplicationServices, \
+        -framework ApplicationServices \
+        $(SUPPORT_OUTPUTDIR)/native/java.base/libjli_static.a, \
     LIBS_windows := $(WIN_JAVA_LIB) advapi32.lib \
         $(SUPPORT_OUTPUTDIR)/native/java.base/jli_static.lib, \
     VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \
--- a/make/lib/LibCommon.gmk	Mon Dec 14 14:12:17 2015 -0800
+++ b/make/lib/LibCommon.gmk	Tue Dec 22 09:14:16 2015 -0800
@@ -46,6 +46,12 @@
   endif
 endif
 
+# SetupNativeCompilation now supports debug symbols on macosx for hotspot.
+# Disable it here for the jdk libraries until we decide to enable them.
+ifeq ($(OPENJDK_TARGET_OS), macosx)
+  ENABLE_DEBUG_SYMBOLS := false
+endif
+
 ################################################################################
 # Find the default set of src dirs for a native library.
 # Param 1 - module name
--- a/src/java.base/linux/classes/sun/nio/ch/EPollSelectorImpl.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/linux/classes/sun/nio/ch/EPollSelectorImpl.java	Tue Dec 22 09:14:16 2015 -0800
@@ -29,7 +29,6 @@
 import java.nio.channels.*;
 import java.nio.channels.spi.*;
 import java.util.*;
-import sun.misc.*;
 
 /**
  * An implementation of Selector for Linux 2.6+ kernels that uses
@@ -50,7 +49,7 @@
     private Map<Integer,SelectionKeyImpl> fdToKey;
 
     // True if this Selector has been closed
-    private volatile boolean closed = false;
+    private volatile boolean closed;
 
     // Lock for interrupt triggering and clearing
     private final Object interruptLock = new Object();
--- a/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java	Tue Dec 22 09:14:16 2015 -0800
@@ -93,7 +93,7 @@
 
     // Instance of this provider, so we don't have to call the provider list
     // to find ourselves or run the risk of not being in the list.
-    private static volatile SunJCE instance = null;
+    private static volatile SunJCE instance;
 
     // lazy initialize SecureRandom to avoid potential recursion if Sun
     // provider has not been installed yet
--- a/src/java.base/share/classes/java/io/CharArrayReader.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/io/CharArrayReader.java	Tue Dec 22 09:14:16 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -225,9 +225,12 @@
      * Closes the stream and releases any system resources associated with
      * it.  Once the stream has been closed, further read(), ready(),
      * mark(), reset(), or skip() invocations will throw an IOException.
-     * Closing a previously closed stream has no effect.
+     * Closing a previously closed stream has no effect. This method will block
+     * while there is another thread blocking on the reader.
      */
     public void close() {
-        buf = null;
+        synchronized (lock) {
+            buf = null;
+        }
     }
 }
--- a/src/java.base/share/classes/java/io/File.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/io/File.java	Tue Dec 22 09:14:16 2015 -0800
@@ -420,11 +420,11 @@
         String scheme = uri.getScheme();
         if ((scheme == null) || !scheme.equalsIgnoreCase("file"))
             throw new IllegalArgumentException("URI scheme is not \"file\"");
-        if (uri.getAuthority() != null)
+        if (uri.getRawAuthority() != null)
             throw new IllegalArgumentException("URI has an authority component");
-        if (uri.getFragment() != null)
+        if (uri.getRawFragment() != null)
             throw new IllegalArgumentException("URI has a fragment component");
-        if (uri.getQuery() != null)
+        if (uri.getRawQuery() != null)
             throw new IllegalArgumentException("URI has a query component");
         String p = uri.getPath();
         if (p.equals(""))
--- a/src/java.base/share/classes/java/io/PipedInputStream.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/io/PipedInputStream.java	Tue Dec 22 09:14:16 2015 -0800
@@ -48,9 +48,9 @@
  * @since   1.0
  */
 public class PipedInputStream extends InputStream {
-    boolean closedByWriter = false;
-    volatile boolean closedByReader = false;
-    boolean connected = false;
+    boolean closedByWriter;
+    volatile boolean closedByReader;
+    boolean connected;
 
         /* REMIND: identification of the read and write sides needs to be
            more sophisticated.  Either using thread groups (but what about
--- a/src/java.base/share/classes/java/io/PushbackReader.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/io/PushbackReader.java	Tue Dec 22 09:14:16 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -241,13 +241,16 @@
      * Closes the stream and releases any system resources associated with
      * it. Once the stream has been closed, further read(),
      * unread(), ready(), or skip() invocations will throw an IOException.
-     * Closing a previously closed stream has no effect.
+     * Closing a previously closed stream has no effect. This method will block
+     * while there is another thread blocking on the reader.
      *
      * @exception  IOException  If an I/O error occurs
      */
     public void close() throws IOException {
-        super.close();
-        buf = null;
+        synchronized (lock) {
+            super.close();
+            buf = null;
+        }
     }
 
     /**
--- a/src/java.base/share/classes/java/io/StringReader.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/io/StringReader.java	Tue Dec 22 09:14:16 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -194,9 +194,12 @@
      * Closes the stream and releases any system resources associated with
      * it. Once the stream has been closed, further read(),
      * ready(), mark(), or reset() invocations will throw an IOException.
-     * Closing a previously closed stream has no effect.
+     * Closing a previously closed stream has no effect. This method will block
+     * while there is another thread blocking on the reader.
      */
     public void close() {
-        str = null;
+        synchronized (lock) {
+            str = null;
+        }
     }
 }
--- a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java	Tue Dec 22 09:14:16 2015 -0800
@@ -25,7 +25,7 @@
 
 package java.lang;
 
-import sun.misc.FloatingDecimal;
+import jdk.internal.math.FloatingDecimal;
 import java.util.Arrays;
 import java.util.Spliterator;
 import java.util.stream.IntStream;
--- a/src/java.base/share/classes/java/lang/Class.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/lang/Class.java	Tue Dec 22 09:14:16 2015 -0800
@@ -2518,7 +2518,7 @@
 
     // Incremented by the VM on each call to JVM TI RedefineClasses()
     // that redefines this class or a superclass.
-    private transient volatile int classRedefinedCount = 0;
+    private transient volatile int classRedefinedCount;
 
     // Lazily create and cache ReflectionData
     private ReflectionData<T> reflectionData() {
@@ -3331,7 +3331,8 @@
      * uncloned, cached, and shared by all callers.
      */
     T[] getEnumConstantsShared() {
-        if (enumConstants == null) {
+        T[] constants = enumConstants;
+        if (constants == null) {
             if (!isEnum()) return null;
             try {
                 final Method values = getMethod("values");
@@ -3344,16 +3345,16 @@
                         });
                 @SuppressWarnings("unchecked")
                 T[] temporaryConstants = (T[])values.invoke(null);
-                enumConstants = temporaryConstants;
+                enumConstants = constants = temporaryConstants;
             }
             // These can happen when users concoct enum-like classes
             // that don't comply with the enum spec.
             catch (InvocationTargetException | NoSuchMethodException |
                    IllegalAccessException ex) { return null; }
         }
-        return enumConstants;
+        return constants;
     }
-    private transient volatile T[] enumConstants = null;
+    private transient volatile T[] enumConstants;
 
     /**
      * Returns a map from simple name to enum constant.  This package-private
@@ -3363,19 +3364,21 @@
      * created lazily on first use.  Typically it won't ever get created.
      */
     Map<String, T> enumConstantDirectory() {
-        if (enumConstantDirectory == null) {
+        Map<String, T> directory = enumConstantDirectory;
+        if (directory == null) {
             T[] universe = getEnumConstantsShared();
             if (universe == null)
                 throw new IllegalArgumentException(
                     getName() + " is not an enum type");
-            Map<String, T> m = new HashMap<>(2 * universe.length);
-            for (T constant : universe)
-                m.put(((Enum<?>)constant).name(), constant);
-            enumConstantDirectory = m;
+            directory = new HashMap<>(2 * universe.length);
+            for (T constant : universe) {
+                directory.put(((Enum<?>)constant).name(), constant);
+            }
+            enumConstantDirectory = directory;
         }
-        return enumConstantDirectory;
+        return directory;
     }
-    private transient volatile Map<String, T> enumConstantDirectory = null;
+    private transient volatile Map<String, T> enumConstantDirectory;
 
     /**
      * Casts an object to the class or interface represented
--- a/src/java.base/share/classes/java/lang/Double.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/lang/Double.java	Tue Dec 22 09:14:16 2015 -0800
@@ -25,8 +25,8 @@
 
 package java.lang;
 
-import sun.misc.FloatingDecimal;
-import sun.misc.DoubleConsts;
+import jdk.internal.math.FloatingDecimal;
+import jdk.internal.math.DoubleConsts;
 import jdk.internal.HotSpotIntrinsicCandidate;
 
 /**
--- a/src/java.base/share/classes/java/lang/Float.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/lang/Float.java	Tue Dec 22 09:14:16 2015 -0800
@@ -25,9 +25,9 @@
 
 package java.lang;
 
-import sun.misc.FloatingDecimal;
-import sun.misc.FloatConsts;
-import sun.misc.DoubleConsts;
+import jdk.internal.math.FloatingDecimal;
+import jdk.internal.math.FloatConsts;
+import jdk.internal.math.DoubleConsts;
 import jdk.internal.HotSpotIntrinsicCandidate;
 
 /**
--- a/src/java.base/share/classes/java/lang/InheritableThreadLocal.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/lang/InheritableThreadLocal.java	Tue Dec 22 09:14:16 2015 -0800
@@ -40,6 +40,11 @@
  * maintained in the variable (e.g., User ID, Transaction ID) must be
  * automatically transmitted to any child threads that are created.
  *
+ * <p>Note: During the creation of a new {@link
+ * Thread#Thread(ThreadGroup,Runnable,String,long,boolean) thread}, it is
+ * possible to <i>opt out</i> of receiving initial values for inheritable
+ * thread-local variables.
+ *
  * @author  Josh Bloch and Doug Lea
  * @see     ThreadLocal
  * @since   1.2
--- a/src/java.base/share/classes/java/lang/Math.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/lang/Math.java	Tue Dec 22 09:14:16 2015 -0800
@@ -26,8 +26,8 @@
 package java.lang;
 
 import java.util.Random;
-import sun.misc.FloatConsts;
-import sun.misc.DoubleConsts;
+import jdk.internal.math.FloatConsts;
+import jdk.internal.math.DoubleConsts;
 import jdk.internal.HotSpotIntrinsicCandidate;
 
 /**
--- a/src/java.base/share/classes/java/lang/StackWalker.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/lang/StackWalker.java	Tue Dec 22 09:14:16 2015 -0800
@@ -304,8 +304,8 @@
     }
 
     /**
-     * Returns a {@code StackWalker} instance with the given {@ocde options} specifying
-     * the stack frame information it can access. If the given {@ocde options}
+     * Returns a {@code StackWalker} instance with the given {@code options} specifying
+     * the stack frame information it can access. If the given {@code options}
      * is empty, this {@code StackWalker} is configured to skip all
      * {@linkplain Option#SHOW_HIDDEN_FRAMES hidden frames} and no
      * {@linkplain Option#RETAIN_CLASS_REFERENCE class reference} is retained.
--- a/src/java.base/share/classes/java/lang/StrictMath.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/lang/StrictMath.java	Tue Dec 22 09:14:16 2015 -0800
@@ -26,7 +26,7 @@
 package java.lang;
 
 import java.util.Random;
-import sun.misc.DoubleConsts;
+import jdk.internal.math.DoubleConsts;
 import jdk.internal.HotSpotIntrinsicCandidate;
 
 /**
--- a/src/java.base/share/classes/java/lang/StringUTF16.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/lang/StringUTF16.java	Tue Dec 22 09:14:16 2015 -0800
@@ -120,7 +120,8 @@
     public static byte[] toBytes(char[] value, int off, int len) {
         byte[] val = newBytesFor(len);
         for (int i = 0; i < len; i++) {
-            putChar(val, i, value[off++]);
+            putChar(val, i, value[off]);
+            off++;
         }
         return val;
     }
@@ -145,11 +146,14 @@
     @HotSpotIntrinsicCandidate
     private static int compress(char[] src, int srcOff, byte[] dst, int dstOff, int len) {
         for (int i = 0; i < len; i++) {
-            int c = src[srcOff++];
-            if (c >>> 8 != 0) {
-                return 0;
+            char c = src[srcOff];
+            if (c > 0xFF) {
+                len = 0;
+                break;
             }
-            dst[dstOff++] = (byte)c;
+            dst[dstOff] = (byte)c;
+            srcOff++;
+            dstOff++;
         }
         return len;
     }
@@ -160,11 +164,14 @@
         // We need a range check here because 'getChar' has no checks
         checkBoundsOffCount(srcOff, len, src.length);
         for (int i = 0; i < len; i++) {
-            int c = getChar(src, srcOff++);
-            if (c >>> 8 != 0) {
-                return 0;
+            char c = getChar(src, srcOff);
+            if (c > 0xFF) {
+                len = 0;
+                break;
             }
-            dst[dstOff++] = (byte)c;
+            dst[dstOff] = (byte)c;
+            srcOff++;
+            dstOff++;
         }
         return len;
     }
@@ -581,7 +588,7 @@
             bits |= cp;
             putChar(result, i, cp);
         }
-        if (bits >>> 8 != 0) {
+        if (bits > 0xFF) {
             return new String(result, UTF16);
         } else {
             return newString(result, 0, len);
@@ -678,7 +685,7 @@
             bits |= cp;
             putChar(result, i, cp);
         }
-        if (bits >>> 8 != 0) {
+        if (bits > 0xFF) {
             return new String(result, UTF16);
         } else {
             return newString(result, 0, len);
--- a/src/java.base/share/classes/java/lang/System.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/lang/System.java	Tue Dec 22 09:14:16 2015 -0800
@@ -132,7 +132,7 @@
 
     /* The security manager for the system.
      */
-    private static volatile SecurityManager security = null;
+    private static volatile SecurityManager security;
 
     /**
      * Reassigns the "standard" input stream.
@@ -206,7 +206,7 @@
         setErr0(err);
     }
 
-    private static volatile Console cons = null;
+    private static volatile Console cons;
     /**
      * Returns the unique {@link java.io.Console Console} object associated
      * with the current Java virtual machine, if any.
@@ -216,12 +216,13 @@
      * @since   1.6
      */
      public static Console console() {
-         if (cons == null) {
+         Console c = cons;
+         if (c == null) {
              synchronized (System.class) {
-                 cons = SharedSecrets.getJavaIOAccess().console();
+                 cons = c = SharedSecrets.getJavaIOAccess().console();
              }
          }
-         return cons;
+         return c;
      }
 
     /**
--- a/src/java.base/share/classes/java/lang/Thread.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/lang/Thread.java	Tue Dec 22 09:14:16 2015 -0800
@@ -207,12 +207,10 @@
     /* For generating thread ID */
     private static long threadSeqNumber;
 
-    /* Java thread status for tools,
-     * initialized to indicate thread 'not yet started'
+    /*
+     * Java thread status for tools, default indicates thread 'not yet started'
      */
-
-    private volatile int threadStatus = 0;
-
+    private volatile int threadStatus;
 
     private static synchronized long nextThreadID() {
         return ++threadSeqNumber;
@@ -344,11 +342,11 @@
 
     /**
      * Initializes a Thread with the current AccessControlContext.
-     * @see #init(ThreadGroup,Runnable,String,long,AccessControlContext)
+     * @see #init(ThreadGroup,Runnable,String,long,AccessControlContext,boolean)
      */
     private void init(ThreadGroup g, Runnable target, String name,
                       long stackSize) {
-        init(g, target, name, stackSize, null);
+        init(g, target, name, stackSize, null, true);
     }
 
     /**
@@ -361,9 +359,12 @@
      *        zero to indicate that this parameter is to be ignored.
      * @param acc the AccessControlContext to inherit, or
      *            AccessController.getContext() if null
+     * @param inheritThreadLocals if {@code true}, inherit initial values for
+     *            inheritable thread-locals from the constructing thread
      */
     private void init(ThreadGroup g, Runnable target, String name,
-                      long stackSize, AccessControlContext acc) {
+                      long stackSize, AccessControlContext acc,
+                      boolean inheritThreadLocals) {
         if (name == null) {
             throw new NullPointerException("name cannot be null");
         }
@@ -414,7 +415,7 @@
                 acc != null ? acc : AccessController.getContext();
         this.target = target;
         setPriority(priority);
-        if (parent.inheritableThreadLocals != null)
+        if (inheritThreadLocals && parent.inheritableThreadLocals != null)
             this.inheritableThreadLocals =
                 ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
         /* Stash the specified stack size in case the VM cares */
@@ -468,7 +469,7 @@
      * This is not a public constructor.
      */
     Thread(Runnable target, AccessControlContext acc) {
-        init(null, target, "Thread-" + nextThreadNum(), 0, acc);
+        init(null, target, "Thread-" + nextThreadNum(), 0, acc, true);
     }
 
     /**
@@ -678,6 +679,62 @@
     }
 
     /**
+     * Allocates a new {@code Thread} object so that it has {@code target}
+     * as its run object, has the specified {@code name} as its name,
+     * belongs to the thread group referred to by {@code group}, has
+     * the specified {@code stackSize}, and inherits initial values for
+     * {@linkplain InheritableThreadLocal inheritable thread-local} variables
+     * if {@code inheritThreadLocals} is {@code true}.
+     *
+     * <p> This constructor is identical to {@link
+     * #Thread(ThreadGroup,Runnable,String,long)} with the added ability to
+     * suppress, or not, the inheriting of initial values for inheritable
+     * thread-local variables from the constructing thread. This allows for
+     * finer grain control over inheritable thread-locals. Care must be taken
+     * when passing a value of {@code false} for {@code inheritThreadLocals},
+     * as it may lead to unexpected behavior if the new thread executes code
+     * that expects a specific thread-local value to be inherited.
+     *
+     * <p> Specifying a value of {@code true} for the {@code inheritThreadLocals}
+     * parameter will cause this constructor to behave exactly like the
+     * {@code Thread(ThreadGroup, Runnable, String, long)} constructor.
+     *
+     * @param  group
+     *         the thread group. If {@code null} and there is a security
+     *         manager, the group is determined by {@linkplain
+     *         SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}.
+     *         If there is not a security manager or {@code
+     *         SecurityManager.getThreadGroup()} returns {@code null}, the group
+     *         is set to the current thread's thread group.
+     *
+     * @param  target
+     *         the object whose {@code run} method is invoked when this thread
+     *         is started. If {@code null}, this thread's run method is invoked.
+     *
+     * @param  name
+     *         the name of the new thread
+     *
+     * @param  stackSize
+     *         the desired stack size for the new thread, or zero to indicate
+     *         that this parameter is to be ignored
+     *
+     * @param  inheritThreadLocals
+     *         if {@code true}, inherit initial values for inheritable
+     *         thread-locals from the constructing thread, otherwise no initial
+     *         values are inherited
+     *
+     * @throws  SecurityException
+     *          if the current thread cannot create a thread in the specified
+     *          thread group
+     *
+     * @since 9
+     */
+    public Thread(ThreadGroup group, Runnable target, String name,
+                  long stackSize, boolean inheritThreadLocals) {
+        init(group, target, name, stackSize, null, inheritThreadLocals);
+    }
+
+    /**
      * Causes this thread to begin execution; the Java Virtual Machine
      * calls the <code>run</code> method of this thread.
      * <p>
--- a/src/java.base/share/classes/java/lang/invoke/CallSite.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/lang/invoke/CallSite.java	Tue Dec 22 09:14:16 2015 -0800
@@ -83,7 +83,6 @@
  */
 abstract
 public class CallSite {
-    static { MethodHandleImpl.initStatics(); }
 
     // The actual payload of this call site:
     /*package-private*/
--- a/src/java.base/share/classes/java/lang/invoke/MemberName.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/lang/invoke/MemberName.java	Tue Dec 22 09:14:16 2015 -0800
@@ -1073,11 +1073,6 @@
         }
     }
 
-//    static {
-//        System.out.println("Hello world!  My methods are:");
-//        System.out.println(Factory.INSTANCE.getMethods(MemberName.class, true, null));
-//    }
-
     static {
         // Allow privileged classes outside of java.lang
         jdk.internal.misc.SharedSecrets.setJavaLangInvokeAccess(new jdk.internal.misc.JavaLangInvokeAccess() {
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandle.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandle.java	Tue Dec 22 09:14:16 2015 -0800
@@ -420,7 +420,6 @@
  * @author John Rose, JSR 292 EG
  */
 public abstract class MethodHandle {
-    static { MethodHandleImpl.initStatics(); }
 
     /**
      * Internal marker interface which distinguishes (to the Java compiler)
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java	Tue Dec 22 09:14:16 2015 -0800
@@ -32,7 +32,6 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.function.Function;
-import java.util.stream.Collectors;
 
 import sun.invoke.empty.Empty;
 import sun.invoke.util.ValueConversions;
@@ -65,11 +64,6 @@
 
     /// Factory methods to create method handles:
 
-    static void initStatics() {
-        // Trigger selected static initializations.
-        MemberName.Factory.INSTANCE.getClass();
-    }
-
     static MethodHandle makeArrayElementAccessor(Class<?> arrayClass, boolean isSetter) {
         if (arrayClass == Object[].class)
             return (isSetter ? ArrayAccessor.OBJECT_ARRAY_SETTER : ArrayAccessor.OBJECT_ARRAY_GETTER);
@@ -700,33 +694,43 @@
     MethodHandle makeBlockInliningWrapper(MethodHandle target) {
         LambdaForm lform;
         if (DONT_INLINE_THRESHOLD > 0) {
-            lform = PRODUCE_BLOCK_INLINING_FORM.apply(target);
+            lform = Makers.PRODUCE_BLOCK_INLINING_FORM.apply(target);
         } else {
-            lform = PRODUCE_REINVOKER_FORM.apply(target);
+            lform = Makers.PRODUCE_REINVOKER_FORM.apply(target);
         }
         return new CountingWrapper(target, lform,
-                PRODUCE_BLOCK_INLINING_FORM, PRODUCE_REINVOKER_FORM,
+                Makers.PRODUCE_BLOCK_INLINING_FORM, Makers.PRODUCE_REINVOKER_FORM,
                                    DONT_INLINE_THRESHOLD);
     }
 
-    /** Constructs reinvoker lambda form which block inlining during JIT-compilation for a particular method handle */
-    private static final Function<MethodHandle, LambdaForm> PRODUCE_BLOCK_INLINING_FORM = new Function<MethodHandle, LambdaForm>() {
-        @Override
-        public LambdaForm apply(MethodHandle target) {
-            return DelegatingMethodHandle.makeReinvokerForm(target,
-                               MethodTypeForm.LF_DELEGATE_BLOCK_INLINING, CountingWrapper.class, "reinvoker.dontInline", false,
-                               DelegatingMethodHandle.NF_getTarget, CountingWrapper.NF_maybeStopCounting);
-        }
-    };
+    private final static class Makers {
+        /** Constructs reinvoker lambda form which block inlining during JIT-compilation for a particular method handle */
+        static final Function<MethodHandle, LambdaForm> PRODUCE_BLOCK_INLINING_FORM = new Function<MethodHandle, LambdaForm>() {
+            @Override
+            public LambdaForm apply(MethodHandle target) {
+                return DelegatingMethodHandle.makeReinvokerForm(target,
+                                   MethodTypeForm.LF_DELEGATE_BLOCK_INLINING, CountingWrapper.class, "reinvoker.dontInline", false,
+                                   DelegatingMethodHandle.NF_getTarget, CountingWrapper.NF_maybeStopCounting);
+            }
+        };
 
-    /** Constructs simple reinvoker lambda form for a particular method handle */
-    private static final Function<MethodHandle, LambdaForm> PRODUCE_REINVOKER_FORM = new Function<MethodHandle, LambdaForm>() {
-        @Override
-        public LambdaForm apply(MethodHandle target) {
-            return DelegatingMethodHandle.makeReinvokerForm(target,
-                    MethodTypeForm.LF_DELEGATE, DelegatingMethodHandle.class, DelegatingMethodHandle.NF_getTarget);
-        }
-    };
+        /** Constructs simple reinvoker lambda form for a particular method handle */
+        static final Function<MethodHandle, LambdaForm> PRODUCE_REINVOKER_FORM = new Function<MethodHandle, LambdaForm>() {
+            @Override
+            public LambdaForm apply(MethodHandle target) {
+                return DelegatingMethodHandle.makeReinvokerForm(target,
+                        MethodTypeForm.LF_DELEGATE, DelegatingMethodHandle.class, DelegatingMethodHandle.NF_getTarget);
+            }
+        };
+
+        /** Maker of type-polymorphic varargs */
+        static final ClassValue<MethodHandle[]> TYPED_COLLECTORS = new ClassValue<MethodHandle[]>() {
+            @Override
+            protected MethodHandle[] computeValue(Class<?> type) {
+                return new MethodHandle[MAX_JVM_ARITY + 1];
+            }
+        };
+    }
 
     /**
      * Counting method handle. It has 2 states: counting and non-counting.
@@ -1527,15 +1531,6 @@
             return MethodHandles.collectArguments(rightFill, 0, midFill);
     }
 
-    // Type-polymorphic version of varargs maker.
-    private static final ClassValue<MethodHandle[]> TYPED_COLLECTORS
-        = new ClassValue<MethodHandle[]>() {
-            @Override
-            protected MethodHandle[] computeValue(Class<?> type) {
-                return new MethodHandle[256];
-            }
-    };
-
     static final int MAX_JVM_ARITY = 255;  // limit imposed by the JVM
 
     /** Return a method handle that takes the indicated number of
@@ -1557,7 +1552,7 @@
         if (elemType == Object.class)
             return varargsArray(nargs);
         // other cases:  primitive arrays, subtypes of Object[]
-        MethodHandle cache[] = TYPED_COLLECTORS.get(elemType);
+        MethodHandle cache[] = Makers.TYPED_COLLECTORS.get(elemType);
         MethodHandle mh = nargs < cache.length ? cache[nargs] : null;
         if (mh != null)  return mh;
         if (nargs == 0) {
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java	Tue Dec 22 09:14:16 2015 -0800
@@ -87,9 +87,6 @@
     private static native void registerNatives();
     static {
         registerNatives();
-
-        // The JVM calls MethodHandleNatives.<clinit>.  Cascade the <clinit> calls as needed:
-        MethodHandleImpl.initStatics();
     }
 
     /**
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java	Tue Dec 22 09:14:16 2015 -0800
@@ -61,7 +61,7 @@
     private MethodHandles() { }  // do not instantiate
 
     private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory();
-    static { MethodHandleImpl.initStatics(); }
+
     // See IMPL_LOOKUP below.
 
     //// Method handle creation from ordinary methods.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/ref/Cleaner.java	Tue Dec 22 09:14:16 2015 -0800
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.ref;
+
+import java.util.Objects;
+import java.util.concurrent.ThreadFactory;
+
+import jdk.internal.misc.CleanerImpl;
+
+/**
+ * {@code Cleaner} manages a set of object references and corresponding cleaning actions.
+ * <p>
+ * Cleaning actions are {@link #register(Object object, Runnable action) registered}
+ * to run after the cleaner is notified that the object has become
+ * phantom reachable.
+ * The cleaner uses {@link PhantomReference} and {@link ReferenceQueue} to be
+ * notified when the <a href="package-summary.html#reachability">reachability</a>
+ * changes.
+ * <p>
+ * Each cleaner operates independently, managing the pending cleaning actions
+ * and handling threading and termination when the cleaner is no longer in use.
+ * Registering an object reference and corresponding cleaning action returns
+ * a {@link Cleanable Cleanable}. The most efficient use is to explicitly invoke
+ * the {@link Cleanable#clean clean} method when the object is closed or
+ * no longer needed.
+ * The cleaning action is a {@link Runnable} to be invoked at most once when
+ * the object has become phantom reachable unless it has already been explicitly cleaned.
+ * Note that the cleaning action must not refer to the object being registered.
+ * If so, the object will not become phantom reachable and the cleaning action
+ * will not be invoked automatically.
+ * <p>
+ * The execution of the cleaning action is performed
+ * by a thread associated with the cleaner.
+ * All exceptions thrown by the cleaning action are ignored.
+ * The cleaner and other cleaning actions are not affected by
+ * exceptions in a cleaning action.
+ * The thread runs until all registered cleaning actions have
+ * completed and the cleaner itself is reclaimed by the garbage collector.
+ * <p>
+ * The behavior of cleaners during {@link System#exit(int) System.exit}
+ * is implementation specific. No guarantees are made relating
+ * to whether cleaning actions are invoked or not.
+ * <p>
+ * Unless otherwise noted, passing a {@code null} argument to a constructor or
+ * method in this class will cause a
+ * {@link java.lang.NullPointerException NullPointerException} to be thrown.
+ *
+ * @apiNote
+ * The cleaning action is invoked only after the associated object becomes
+ * phantom reachable, so it is important that the object implementing the
+ * cleaning action does not hold references to the object.
+ * In this example, a static class encapsulates the cleaning state and action.
+ * An "inner" class, anonymous or not,  must not be used because it implicitly
+ * contains a reference to the outer instance, preventing it from becoming
+ * phantom reachable.
+ * The choice of a new cleaner or sharing an existing cleaner is determined
+ * by the use case.
+ * <p>
+ * If the CleaningExample is used in a try-finally block then the
+ * {@code close} method calls the cleaning action.
+ * If the {@code close} method is not called, the cleaning action is called
+ * by the Cleaner when the CleaningExample instance has become phantom reachable.
+ * <pre>{@code
+ * public class CleaningExample implements AutoCloseable {
+ *        // A cleaner, preferably one shared within a library
+ *        private static final Cleaner cleaner = <cleaner>;
+ *
+ *        static class State implements Runnable {
+ *
+ *            State(...) {
+ *                // initialize State needed for cleaning action
+ *            }
+ *
+ *            public void run() {
+ *                // cleanup action accessing State, executed at most once
+ *            }
+ *        }
+ *
+ *        private final State;
+ *        private final Cleaner.Cleanable cleanable
+ *
+ *        public CleaningExample() {
+ *            this.state = new State(...);
+ *            this.cleanable = cleaner.register(this, state);
+ *        }
+ *
+ *        public void close() {
+ *            cleanable.clean();
+ *        }
+ *    }
+ * }</pre>
+ * The cleaning action could be a lambda but all too easily will capture
+ * the object reference, by referring to fields of the object being cleaned,
+ * preventing the object from becoming phantom reachable.
+ * Using a static nested class, as above, will avoid accidentally retaining the
+ * object reference.
+ * <p>
+ * <a name="compatible-cleaners"></a>
+ * Cleaning actions should be prepared to be invoked concurrently with
+ * other cleaning actions.
+ * Typically the cleaning actions should be very quick to execute
+ * and not block. If the cleaning action blocks, it may delay processing
+ * other cleaning actions registered to the same cleaner.
+ * All cleaning actions registered to a cleaner should be mutually compatible.
+ * @since 9
+ */
+public final class Cleaner {
+
+    /**
+     * The Cleaner implementation.
+     */
+    final CleanerImpl impl;
+
+    static {
+        CleanerImpl.setCleanerImplAccess((Cleaner c) -> c.impl);
+    }
+
+    /**
+     * Construct a Cleaner implementation and start it.
+     */
+    private Cleaner() {
+        impl = new CleanerImpl();
+    }
+
+    /**
+     * Returns a new {@code Cleaner}.
+     * <p>
+     * The cleaner creates a {@link Thread#setDaemon(boolean) daemon thread}
+     * to process the phantom reachable objects and to invoke cleaning actions.
+     * The {@linkplain java.lang.Thread#getContextClassLoader context class loader}
+     * of the thread is set to the
+     * {@link ClassLoader#getSystemClassLoader() system class loader}.
+     * The thread has no permissions, enforced only if a
+     * {@link java.lang.System#setSecurityManager(SecurityManager) SecurityManager is set}.
+     * <p>
+     * The cleaner terminates when it is phantom reachable and all of the
+     * registered cleaning actions are complete.
+     *
+     * @return a new {@code Cleaner}
+     *
+     * @throws  SecurityException  if the current thread is not allowed to
+     *               create or start the thread.
+     */
+    public static Cleaner create() {
+        Cleaner cleaner = new Cleaner();
+        cleaner.impl.start(cleaner, null);
+        return cleaner;
+    }
+
+    /**
+     * Returns a new {@code Cleaner} using a {@code Thread} from the {@code ThreadFactory}.
+     * <p>
+     * A thread from the thread factory's {@link ThreadFactory#newThread(Runnable) newThread}
+     * method is set to be a {@link Thread#setDaemon(boolean) daemon thread}
+     * and started to process phantom reachable objects and invoke cleaning actions.
+     * On each call the {@link ThreadFactory#newThread(Runnable) thread factory}
+     * must provide a Thread that is suitable for performing the cleaning actions.
+     * <p>
+     * The cleaner terminates when it is phantom reachable and all of the
+     * registered cleaning actions are complete.
+     *
+     * @param threadFactory a {@code ThreadFactory} to return a new {@code Thread}
+     *                      to process cleaning actions
+     * @return a new {@code Cleaner}
+     *
+     * @throws  IllegalThreadStateException  if the thread from the thread
+     *               factory was {@link Thread.State#NEW not a new thread}.
+     * @throws  SecurityException  if the current thread is not allowed to
+     *               create or start the thread.
+     */
+    public static Cleaner create(ThreadFactory threadFactory) {
+        Objects.requireNonNull(threadFactory, "threadFactory");
+        Cleaner cleaner = new Cleaner();
+        cleaner.impl.start(cleaner, threadFactory);
+        return cleaner;
+    }
+
+    /**
+     * Registers an object and a cleaning action to run when the object
+     * becomes phantom reachable.
+     * Refer to the <a href="#compatible-cleaners">API Note</a> above for
+     * cautions about the behavior of cleaning actions.
+     *
+     * @param obj   the object to monitor
+     * @param action a {@code Runnable} to invoke when the object becomes phantom reachable
+     * @return a {@code Cleanable} instance
+     */
+    public Cleanable register(Object obj, Runnable action) {
+        Objects.requireNonNull(obj, "obj");
+        Objects.requireNonNull(action, "action");
+        return new CleanerImpl.PhantomCleanableRef(obj, this, action);
+    }
+
+    /**
+     * {@code Cleanable} represents an object and a
+     * cleaning action registered in a {@code Cleaner}.
+     * @since 9
+     */
+    public interface Cleanable {
+        /**
+         * Unregisters the cleanable and invokes the cleaning action.
+         * The cleanable's cleaning action is invoked at most once
+         * regardless of the number of calls to {@code clean}.
+         */
+        void clean();
+    }
+
+}
--- a/src/java.base/share/classes/java/lang/ref/Finalizer.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/lang/ref/Finalizer.java	Tue Dec 22 09:14:16 2015 -0800
@@ -29,7 +29,6 @@
 import java.security.AccessController;
 import jdk.internal.misc.JavaLangAccess;
 import jdk.internal.misc.SharedSecrets;
-import sun.misc.ManagedLocalsThread;
 import sun.misc.VM;
 
 final class Finalizer extends FinalReference<Object> { /* Package-private; must be in
@@ -131,7 +130,7 @@
                     for (ThreadGroup tgn = tg;
                          tgn != null;
                          tg = tgn, tgn = tg.getParent());
-                    Thread sft = new ManagedLocalsThread(tg, proc, "Secondary finalizer");
+                    Thread sft = new Thread(tg, proc, "Secondary finalizer", 0, false);
                     sft.start();
                     try {
                         sft.join();
@@ -190,10 +189,10 @@
                 }}});
     }
 
-    private static class FinalizerThread extends ManagedLocalsThread {
+    private static class FinalizerThread extends Thread {
         private volatile boolean running;
         FinalizerThread(ThreadGroup g) {
-            super(g, "Finalizer");
+            super(g, null, "Finalizer", 0, false);
         }
         public void run() {
             // in case of recursive call to run()
--- a/src/java.base/share/classes/java/lang/ref/Reference.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/lang/ref/Reference.java	Tue Dec 22 09:14:16 2015 -0800
@@ -29,7 +29,6 @@
 import jdk.internal.HotSpotIntrinsicCandidate;
 import jdk.internal.misc.JavaLangRefAccess;
 import jdk.internal.misc.SharedSecrets;
-import sun.misc.ManagedLocalsThread;
 
 /**
  * Abstract base class for reference objects.  This class defines the
@@ -128,7 +127,7 @@
 
     /* High-priority thread to enqueue pending References
      */
-    private static class ReferenceHandler extends ManagedLocalsThread {
+    private static class ReferenceHandler extends Thread {
 
         private static void ensureClassInitialized(Class<?> clazz) {
             try {
@@ -147,7 +146,7 @@
         }
 
         ReferenceHandler(ThreadGroup g, String name) {
-            super(g, name);
+            super(g, null, name, 0, false);
         }
 
         public void run() {
--- a/src/java.base/share/classes/java/lang/ref/ReferenceQueue.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/lang/ref/ReferenceQueue.java	Tue Dec 22 09:14:16 2015 -0800
@@ -53,7 +53,7 @@
 
     private static class Lock { };
     private Lock lock = new Lock();
-    private volatile Reference<? extends T> head = null;
+    private volatile Reference<? extends T> head;
     private long queueLength = 0;
 
     boolean enqueue(Reference<? extends T> r) { /* Called only by Reference class */
--- a/src/java.base/share/classes/java/lang/ref/package-info.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/lang/ref/package-info.java	Tue Dec 22 09:14:16 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -45,6 +45,8 @@
  * (or values) from being reclaimed, and phantom references are for
  * scheduling pre-mortem cleanup actions in a more flexible way than
  * is possible with the Java finalization mechanism.
+ * Post-mortem cleanup actions can be registered and managed by a
+ * {@link java.lang.ref.Cleaner}.
  *
  * <p> Each reference-object type is implemented by a subclass of the
  * abstract base {@link java.lang.ref.Reference} class.
--- a/src/java.base/share/classes/java/lang/reflect/AnnotatedArrayType.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/lang/reflect/AnnotatedArrayType.java	Tue Dec 22 09:14:16 2015 -0800
@@ -42,4 +42,19 @@
      * @see GenericArrayType#getGenericComponentType()
      */
     AnnotatedType  getAnnotatedGenericComponentType();
+
+    /**
+     * Returns the potentially annotated type that this type is a member of, if
+     * this type represents a nested type. For example, if this type is
+     * {@code @TA O<T>.I<S>}, return a representation of {@code @TA O<T>}.
+     *
+     * <p>Returns {@code null} for an {@code AnnotatedType} that is an instance
+     *     of {@code AnnotatedArrayType}.
+     *
+     * @return {@code null}
+     *
+     * @since 1.9
+     */
+    @Override
+    AnnotatedType getAnnotatedOwnerType();
 }
--- a/src/java.base/share/classes/java/lang/reflect/AnnotatedParameterizedType.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/lang/reflect/AnnotatedParameterizedType.java	Tue Dec 22 09:14:16 2015 -0800
@@ -41,4 +41,26 @@
      * @see ParameterizedType#getActualTypeArguments()
      */
     AnnotatedType[] getAnnotatedActualTypeArguments();
+
+    /**
+     * Returns the potentially annotated type that this type is a member of, if
+     * this type represents a nested type. For example, if this type is
+     * {@code @TA O<T>.I<S>}, return a representation of {@code @TA O<T>}.
+     *
+     * <p>Returns {@code null} if this {@code AnnotatedType} represents a
+     *     top-level type, or a local or anonymous class, or a primitive type, or
+     *     void.
+     *
+     * @return an {@code AnnotatedType} object representing the potentially
+     *     annotated type that this type is a member of, or {@code null}
+     * @throws TypeNotPresentException if the owner type
+     *     refers to a non-existent type declaration
+     * @throws MalformedParameterizedTypeException if the owner type
+     *     refers to a parameterized type that cannot be instantiated
+     *     for any reason
+     *
+     * @since 1.9
+     */
+    @Override
+    AnnotatedType getAnnotatedOwnerType();
 }
--- a/src/java.base/share/classes/java/lang/reflect/AnnotatedType.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/lang/reflect/AnnotatedType.java	Tue Dec 22 09:14:16 2015 -0800
@@ -36,6 +36,37 @@
 public interface AnnotatedType extends AnnotatedElement {
 
     /**
+     * Returns the potentially annotated type that this type is a member of, if
+     * this type represents a nested type. For example, if this type is
+     * {@code @TA O<T>.I<S>}, return a representation of {@code @TA O<T>}.
+     *
+     * <p>Returns {@code null} if this {@code AnnotatedType} represents a
+     *     top-level type, or a local or anonymous class, or a primitive type, or
+     *     void.
+     *
+     * <p>Returns {@code null} if this {@code AnnotatedType} is an instance of
+     *     {@code AnnotatedArrayType}, {@code AnnotatedTypeVariable}, or
+     *     {@code AnnotatedWildcardType}.
+     *
+     * @implSpec
+     * This default implementation returns {@code null} and performs no other
+     * action.
+     *
+     * @return an {@code AnnotatedType} object representing the potentially
+     *     annotated type that this type is a member of, or {@code null}
+     * @throws TypeNotPresentException if the owner type
+     *     refers to a non-existent type declaration
+     * @throws MalformedParameterizedTypeException if the owner type
+     *     refers to a parameterized type that cannot be instantiated
+     *     for any reason
+     *
+     * @since 1.9
+     */
+    default AnnotatedType getAnnotatedOwnerType() {
+        return null;
+    }
+
+    /**
      * Returns the underlying type that this annotated type represents.
      *
      * @return the type this annotated type represents
--- a/src/java.base/share/classes/java/lang/reflect/AnnotatedTypeVariable.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/lang/reflect/AnnotatedTypeVariable.java	Tue Dec 22 09:14:16 2015 -0800
@@ -43,4 +43,19 @@
      * @see TypeVariable#getBounds()
      */
     AnnotatedType[] getAnnotatedBounds();
+
+    /**
+     * Returns the potentially annotated type that this type is a member of, if
+     * this type represents a nested type. For example, if this type is
+     * {@code @TA O<T>.I<S>}, return a representation of {@code @TA O<T>}.
+     *
+     * <p>Returns {@code null} for an {@code AnnotatedType} that is an instance
+     *     of {@code AnnotatedTypeVariable}.
+     *
+     * @return {@code null}
+     *
+     * @since 1.9
+     */
+    @Override
+    AnnotatedType getAnnotatedOwnerType();
 }
--- a/src/java.base/share/classes/java/lang/reflect/AnnotatedWildcardType.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/lang/reflect/AnnotatedWildcardType.java	Tue Dec 22 09:14:16 2015 -0800
@@ -54,4 +54,19 @@
      * @see WildcardType#getUpperBounds()
      */
     AnnotatedType[] getAnnotatedUpperBounds();
+
+    /**
+     * Returns the potentially annotated type that this type is a member of, if
+     * this type represents a nested type. For example, if this type is
+     * {@code @TA O<T>.I<S>}, return a representation of {@code @TA O<T>}.
+     *
+     * <p>Returns {@code null} for an {@code AnnotatedType} that is an instance
+     *     of {@code AnnotatedWildcardType}.
+     *
+     * @return {@code null}
+     *
+     * @since 1.9
+     */
+    @Override
+    AnnotatedType getAnnotatedOwnerType();
 }
--- a/src/java.base/share/classes/java/lang/reflect/Parameter.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/lang/reflect/Parameter.java	Tue Dec 22 09:14:16 2015 -0800
@@ -205,7 +205,7 @@
         return tmp;
     }
 
-    private transient volatile Type parameterTypeCache = null;
+    private transient volatile Type parameterTypeCache;
 
     /**
      * Returns a {@code Class} object that identifies the
@@ -237,7 +237,7 @@
         return executable.getAnnotatedParameterTypes()[index];
     }
 
-    private transient volatile Class<?> parameterClassCache = null;
+    private transient volatile Class<?> parameterClassCache;
 
     /**
      * Returns {@code true} if this parameter is implicitly declared
--- a/src/java.base/share/classes/java/lang/reflect/Proxy.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/lang/reflect/Proxy.java	Tue Dec 22 09:14:16 2015 -0800
@@ -34,7 +34,6 @@
 import java.util.Objects;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.function.BiFunction;
-import sun.misc.ProxyGenerator;
 import sun.misc.VM;
 import sun.reflect.CallerSensitive;
 import sun.reflect.Reflection;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java	Tue Dec 22 09:14:16 2015 -0800
@@ -0,0 +1,2031 @@
+/*
+ * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.reflect;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.reflect.Array;
+import java.lang.reflect.Method;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import sun.security.action.GetBooleanAction;
+
+/**
+ * ProxyGenerator contains the code to generate a dynamic proxy class
+ * for the java.lang.reflect.Proxy API.
+ *
+ * The external interfaces to ProxyGenerator is the static
+ * "generateProxyClass" method.
+ *
+ * @author      Peter Jones
+ * @since       1.3
+ */
+class ProxyGenerator {
+    /*
+     * In the comments below, "JVMS" refers to The Java Virtual Machine
+     * Specification Second Edition and "JLS" refers to the original
+     * version of The Java Language Specification, unless otherwise
+     * specified.
+     */
+
+    /* generate 1.5-era class file version */
+    private static final int CLASSFILE_MAJOR_VERSION = 49;
+    private static final int CLASSFILE_MINOR_VERSION = 0;
+
+    /*
+     * beginning of constants copied from
+     * sun.tools.java.RuntimeConstants (which no longer exists):
+     */
+
+    /* constant pool tags */
+    private static final int CONSTANT_UTF8              = 1;
+    private static final int CONSTANT_UNICODE           = 2;
+    private static final int CONSTANT_INTEGER           = 3;
+    private static final int CONSTANT_FLOAT             = 4;
+    private static final int CONSTANT_LONG              = 5;
+    private static final int CONSTANT_DOUBLE            = 6;
+    private static final int CONSTANT_CLASS             = 7;
+    private static final int CONSTANT_STRING            = 8;
+    private static final int CONSTANT_FIELD             = 9;
+    private static final int CONSTANT_METHOD            = 10;
+    private static final int CONSTANT_INTERFACEMETHOD   = 11;
+    private static final int CONSTANT_NAMEANDTYPE       = 12;
+
+    /* access and modifier flags */
+    private static final int ACC_PUBLIC                 = 0x00000001;
+    private static final int ACC_PRIVATE                = 0x00000002;
+//  private static final int ACC_PROTECTED              = 0x00000004;
+    private static final int ACC_STATIC                 = 0x00000008;
+    private static final int ACC_FINAL                  = 0x00000010;
+//  private static final int ACC_SYNCHRONIZED           = 0x00000020;
+//  private static final int ACC_VOLATILE               = 0x00000040;
+//  private static final int ACC_TRANSIENT              = 0x00000080;
+//  private static final int ACC_NATIVE                 = 0x00000100;
+//  private static final int ACC_INTERFACE              = 0x00000200;
+//  private static final int ACC_ABSTRACT               = 0x00000400;
+    private static final int ACC_SUPER                  = 0x00000020;
+//  private static final int ACC_STRICT                 = 0x00000800;
+
+    /* opcodes */
+//  private static final int opc_nop                    = 0;
+    private static final int opc_aconst_null            = 1;
+//  private static final int opc_iconst_m1              = 2;
+    private static final int opc_iconst_0               = 3;
+//  private static final int opc_iconst_1               = 4;
+//  private static final int opc_iconst_2               = 5;
+//  private static final int opc_iconst_3               = 6;
+//  private static final int opc_iconst_4               = 7;
+//  private static final int opc_iconst_5               = 8;
+//  private static final int opc_lconst_0               = 9;
+//  private static final int opc_lconst_1               = 10;
+//  private static final int opc_fconst_0               = 11;
+//  private static final int opc_fconst_1               = 12;
+//  private static final int opc_fconst_2               = 13;
+//  private static final int opc_dconst_0               = 14;
+//  private static final int opc_dconst_1               = 15;
+    private static final int opc_bipush                 = 16;
+    private static final int opc_sipush                 = 17;
+    private static final int opc_ldc                    = 18;
+    private static final int opc_ldc_w                  = 19;
+//  private static final int opc_ldc2_w                 = 20;
+    private static final int opc_iload                  = 21;
+    private static final int opc_lload                  = 22;
+    private static final int opc_fload                  = 23;
+    private static final int opc_dload                  = 24;
+    private static final int opc_aload                  = 25;
+    private static final int opc_iload_0                = 26;
+//  private static final int opc_iload_1                = 27;
+//  private static final int opc_iload_2                = 28;
+//  private static final int opc_iload_3                = 29;
+    private static final int opc_lload_0                = 30;
+//  private static final int opc_lload_1                = 31;
+//  private static final int opc_lload_2                = 32;
+//  private static final int opc_lload_3                = 33;
+    private static final int opc_fload_0                = 34;
+//  private static final int opc_fload_1                = 35;
+//  private static final int opc_fload_2                = 36;
+//  private static final int opc_fload_3                = 37;
+    private static final int opc_dload_0                = 38;
+//  private static final int opc_dload_1                = 39;
+//  private static final int opc_dload_2                = 40;
+//  private static final int opc_dload_3                = 41;
+    private static final int opc_aload_0                = 42;
+//  private static final int opc_aload_1                = 43;
+//  private static final int opc_aload_2                = 44;
+//  private static final int opc_aload_3                = 45;
+//  private static final int opc_iaload                 = 46;
+//  private static final int opc_laload                 = 47;
+//  private static final int opc_faload                 = 48;
+//  private static final int opc_daload                 = 49;
+//  private static final int opc_aaload                 = 50;
+//  private static final int opc_baload                 = 51;
+//  private static final int opc_caload                 = 52;
+//  private static final int opc_saload                 = 53;
+//  private static final int opc_istore                 = 54;
+//  private static final int opc_lstore                 = 55;
+//  private static final int opc_fstore                 = 56;
+//  private static final int opc_dstore                 = 57;
+    private static final int opc_astore                 = 58;
+//  private static final int opc_istore_0               = 59;
+//  private static final int opc_istore_1               = 60;
+//  private static final int opc_istore_2               = 61;
+//  private static final int opc_istore_3               = 62;
+//  private static final int opc_lstore_0               = 63;
+//  private static final int opc_lstore_1               = 64;
+//  private static final int opc_lstore_2               = 65;
+//  private static final int opc_lstore_3               = 66;
+//  private static final int opc_fstore_0               = 67;
+//  private static final int opc_fstore_1               = 68;
+//  private static final int opc_fstore_2               = 69;
+//  private static final int opc_fstore_3               = 70;
+//  private static final int opc_dstore_0               = 71;
+//  private static final int opc_dstore_1               = 72;
+//  private static final int opc_dstore_2               = 73;
+//  private static final int opc_dstore_3               = 74;
+    private static final int opc_astore_0               = 75;
+//  private static final int opc_astore_1               = 76;
+//  private static final int opc_astore_2               = 77;
+//  private static final int opc_astore_3               = 78;
+//  private static final int opc_iastore                = 79;
+//  private static final int opc_lastore                = 80;
+//  private static final int opc_fastore                = 81;
+//  private static final int opc_dastore                = 82;
+    private static final int opc_aastore                = 83;
+//  private static final int opc_bastore                = 84;
+//  private static final int opc_castore                = 85;
+//  private static final int opc_sastore                = 86;
+    private static final int opc_pop                    = 87;
+//  private static final int opc_pop2                   = 88;
+    private static final int opc_dup                    = 89;
+//  private static final int opc_dup_x1                 = 90;
+//  private static final int opc_dup_x2                 = 91;
+//  private static final int opc_dup2                   = 92;
+//  private static final int opc_dup2_x1                = 93;
+//  private static final int opc_dup2_x2                = 94;
+//  private static final int opc_swap                   = 95;
+//  private static final int opc_iadd                   = 96;
+//  private static final int opc_ladd                   = 97;
+//  private static final int opc_fadd                   = 98;
+//  private static final int opc_dadd                   = 99;
+//  private static final int opc_isub                   = 100;
+//  private static final int opc_lsub                   = 101;
+//  private static final int opc_fsub                   = 102;
+//  private static final int opc_dsub                   = 103;
+//  private static final int opc_imul                   = 104;
+//  private static final int opc_lmul                   = 105;
+//  private static final int opc_fmul                   = 106;
+//  private static final int opc_dmul                   = 107;
+//  private static final int opc_idiv                   = 108;
+//  private static final int opc_ldiv                   = 109;
+//  private static final int opc_fdiv                   = 110;
+//  private static final int opc_ddiv                   = 111;
+//  private static final int opc_irem                   = 112;
+//  private static final int opc_lrem                   = 113;
+//  private static final int opc_frem                   = 114;
+//  private static final int opc_drem                   = 115;
+//  private static final int opc_ineg                   = 116;
+//  private static final int opc_lneg                   = 117;
+//  private static final int opc_fneg                   = 118;
+//  private static final int opc_dneg                   = 119;
+//  private static final int opc_ishl                   = 120;
+//  private static final int opc_lshl                   = 121;
+//  private static final int opc_ishr                   = 122;
+//  private static final int opc_lshr                   = 123;
+//  private static final int opc_iushr                  = 124;
+//  private static final int opc_lushr                  = 125;
+//  private static final int opc_iand                   = 126;
+//  private static final int opc_land                   = 127;
+//  private static final int opc_ior                    = 128;
+//  private static final int opc_lor                    = 129;
+//  private static final int opc_ixor                   = 130;
+//  private static final int opc_lxor                   = 131;
+//  private static final int opc_iinc                   = 132;
+//  private static final int opc_i2l                    = 133;
+//  private static final int opc_i2f                    = 134;
+//  private static final int opc_i2d                    = 135;
+//  private static final int opc_l2i                    = 136;
+//  private static final int opc_l2f                    = 137;
+//  private static final int opc_l2d                    = 138;
+//  private static final int opc_f2i                    = 139;
+//  private static final int opc_f2l                    = 140;
+//  private static final int opc_f2d                    = 141;
+//  private static final int opc_d2i                    = 142;
+//  private static final int opc_d2l                    = 143;
+//  private static final int opc_d2f                    = 144;
+//  private static final int opc_i2b                    = 145;
+//  private static final int opc_i2c                    = 146;
+//  private static final int opc_i2s                    = 147;
+//  private static final int opc_lcmp                   = 148;
+//  private static final int opc_fcmpl                  = 149;
+//  private static final int opc_fcmpg                  = 150;
+//  private static final int opc_dcmpl                  = 151;
+//  private static final int opc_dcmpg                  = 152;
+//  private static final int opc_ifeq                   = 153;
+//  private static final int opc_ifne                   = 154;
+//  private static final int opc_iflt                   = 155;
+//  private static final int opc_ifge                   = 156;
+//  private static final int opc_ifgt                   = 157;
+//  private static final int opc_ifle                   = 158;
+//  private static final int opc_if_icmpeq              = 159;
+//  private static final int opc_if_icmpne              = 160;
+//  private static final int opc_if_icmplt              = 161;
+//  private static final int opc_if_icmpge              = 162;
+//  private static final int opc_if_icmpgt              = 163;
+//  private static final int opc_if_icmple              = 164;
+//  private static final int opc_if_acmpeq              = 165;
+//  private static final int opc_if_acmpne              = 166;
+//  private static final int opc_goto                   = 167;
+//  private static final int opc_jsr                    = 168;
+//  private static final int opc_ret                    = 169;
+//  private static final int opc_tableswitch            = 170;
+//  private static final int opc_lookupswitch           = 171;
+    private static final int opc_ireturn                = 172;
+    private static final int opc_lreturn                = 173;
+    private static final int opc_freturn                = 174;
+    private static final int opc_dreturn                = 175;
+    private static final int opc_areturn                = 176;
+    private static final int opc_return                 = 177;
+    private static final int opc_getstatic              = 178;
+    private static final int opc_putstatic              = 179;
+    private static final int opc_getfield               = 180;
+//  private static final int opc_putfield               = 181;
+    private static final int opc_invokevirtual          = 182;
+    private static final int opc_invokespecial          = 183;
+    private static final int opc_invokestatic           = 184;
+    private static final int opc_invokeinterface        = 185;
+    private static final int opc_new                    = 187;
+//  private static final int opc_newarray               = 188;
+    private static final int opc_anewarray              = 189;
+//  private static final int opc_arraylength            = 190;
+    private static final int opc_athrow                 = 191;
+    private static final int opc_checkcast              = 192;
+//  private static final int opc_instanceof             = 193;
+//  private static final int opc_monitorenter           = 194;
+//  private static final int opc_monitorexit            = 195;
+    private static final int opc_wide                   = 196;
+//  private static final int opc_multianewarray         = 197;
+//  private static final int opc_ifnull                 = 198;
+//  private static final int opc_ifnonnull              = 199;
+//  private static final int opc_goto_w                 = 200;
+//  private static final int opc_jsr_w                  = 201;
+
+    // end of constants copied from sun.tools.java.RuntimeConstants
+
+    /** name of the superclass of proxy classes */
+    private static final String superclassName = "java/lang/reflect/Proxy";
+
+    /** name of field for storing a proxy instance's invocation handler */
+    private static final String handlerFieldName = "h";
+
+    /** debugging flag for saving generated class files */
+    private static final boolean saveGeneratedFiles =
+        java.security.AccessController.doPrivileged(
+            new GetBooleanAction(
+                "jdk.proxy.ProxyGenerator.saveGeneratedFiles")).booleanValue();
+
+    /**
+     * Generate a public proxy class given a name and a list of proxy interfaces.
+     */
+    static byte[] generateProxyClass(final String name,
+                                     Class<?>[] interfaces) {
+        return generateProxyClass(name, interfaces, (ACC_PUBLIC | ACC_FINAL | ACC_SUPER));
+    }
+
+    /**
+     * Generate a proxy class given a name and a list of proxy interfaces.
+     *
+     * @param name        the class name of the proxy class
+     * @param interfaces  proxy interfaces
+     * @param accessFlags access flags of the proxy class
+    */
+    static byte[] generateProxyClass(final String name,
+                                     Class<?>[] interfaces,
+                                     int accessFlags)
+    {
+        ProxyGenerator gen = new ProxyGenerator(name, interfaces, accessFlags);
+        final byte[] classFile = gen.generateClassFile();
+
+        if (saveGeneratedFiles) {
+            java.security.AccessController.doPrivileged(
+            new java.security.PrivilegedAction<Void>() {
+                public Void run() {
+                    try {
+                        int i = name.lastIndexOf('.');
+                        Path path;
+                        if (i > 0) {
+                            Path dir = Paths.get(name.substring(0, i).replace('.', File.separatorChar));
+                            Files.createDirectories(dir);
+                            path = dir.resolve(name.substring(i+1, name.length()) + ".class");
+                        } else {
+                            path = Paths.get(name + ".class");
+                        }
+                        Files.write(path, classFile);
+                        return null;
+                    } catch (IOException e) {
+                        throw new InternalError(
+                            "I/O exception saving generated file: " + e);
+                    }
+                }
+            });
+        }
+
+        return classFile;
+    }
+
+    /* preloaded Method objects for methods in java.lang.Object */
+    private static Method hashCodeMethod;
+    private static Method equalsMethod;
+    private static Method toStringMethod;
+    static {
+        try {
+            hashCodeMethod = Object.class.getMethod("hashCode");
+            equalsMethod =
+                Object.class.getMethod("equals", new Class<?>[] { Object.class });
+            toStringMethod = Object.class.getMethod("toString");
+        } catch (NoSuchMethodException e) {
+            throw new NoSuchMethodError(e.getMessage());
+        }
+    }
+
+    /** name of proxy class */
+    private String className;
+
+    /** proxy interfaces */
+    private Class<?>[] interfaces;
+
+    /** proxy class access flags */
+    private int accessFlags;
+
+    /** constant pool of class being generated */
+    private ConstantPool cp = new ConstantPool();
+
+    /** FieldInfo struct for each field of generated class */
+    private List<FieldInfo> fields = new ArrayList<>();
+
+    /** MethodInfo struct for each method of generated class */
+    private List<MethodInfo> methods = new ArrayList<>();
+
+    /**
+     * maps method signature string to list of ProxyMethod objects for
+     * proxy methods with that signature
+     */
+    private Map<String, List<ProxyMethod>> proxyMethods = new HashMap<>();
+
+    /** count of ProxyMethod objects added to proxyMethods */
+    private int proxyMethodCount = 0;
+
+    /**
+     * Construct a ProxyGenerator to generate a proxy class with the
+     * specified name and for the given interfaces.
+     *
+     * A ProxyGenerator object contains the state for the ongoing
+     * generation of a particular proxy class.
+     */
+    private ProxyGenerator(String className, Class<?>[] interfaces, int accessFlags) {
+        this.className = className;
+        this.interfaces = interfaces;
+        this.accessFlags = accessFlags;
+    }
+
+    /**
+     * Generate a class file for the proxy class.  This method drives the
+     * class file generation process.
+     */
+    private byte[] generateClassFile() {
+
+        /* ============================================================
+         * Step 1: Assemble ProxyMethod objects for all methods to
+         * generate proxy dispatching code for.
+         */
+
+        /*
+         * Record that proxy methods are needed for the hashCode, equals,
+         * and toString methods of java.lang.Object.  This is done before
+         * the methods from the proxy interfaces so that the methods from
+         * java.lang.Object take precedence over duplicate methods in the
+         * proxy interfaces.
+         */
+        addProxyMethod(hashCodeMethod, Object.class);
+        addProxyMethod(equalsMethod, Object.class);
+        addProxyMethod(toStringMethod, Object.class);
+
+        /*
+         * Now record all of the methods from the proxy interfaces, giving
+         * earlier interfaces precedence over later ones with duplicate
+         * methods.
+         */
+        for (Class<?> intf : interfaces) {
+            for (Method m : intf.getMethods()) {
+                addProxyMethod(m, intf);
+            }
+        }
+
+        /*
+         * For each set of proxy methods with the same signature,
+         * verify that the methods' return types are compatible.
+         */
+        for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
+            checkReturnTypes(sigmethods);
+        }
+
+        /* ============================================================
+         * Step 2: Assemble FieldInfo and MethodInfo structs for all of
+         * fields and methods in the class we are generating.
+         */
+        try {
+            methods.add(generateConstructor());
+
+            for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
+                for (ProxyMethod pm : sigmethods) {
+
+                    // add static field for method's Method object
+                    fields.add(new FieldInfo(pm.methodFieldName,
+                        "Ljava/lang/reflect/Method;",
+                         ACC_PRIVATE | ACC_STATIC));
+
+                    // generate code for proxy method and add it
+                    methods.add(pm.generateMethod());
+                }
+            }
+
+            methods.add(generateStaticInitializer());
+
+        } catch (IOException e) {
+            throw new InternalError("unexpected I/O Exception", e);
+        }
+
+        if (methods.size() > 65535) {
+            throw new IllegalArgumentException("method limit exceeded");
+        }
+        if (fields.size() > 65535) {
+            throw new IllegalArgumentException("field limit exceeded");
+        }
+
+        /* ============================================================
+         * Step 3: Write the final class file.
+         */
+
+        /*
+         * Make sure that constant pool indexes are reserved for the
+         * following items before starting to write the final class file.
+         */
+        cp.getClass(dotToSlash(className));
+        cp.getClass(superclassName);
+        for (Class<?> intf: interfaces) {
+            cp.getClass(dotToSlash(intf.getName()));
+        }
+
+        /*
+         * Disallow new constant pool additions beyond this point, since
+         * we are about to write the final constant pool table.
+         */
+        cp.setReadOnly();
+
+        ByteArrayOutputStream bout = new ByteArrayOutputStream();
+        DataOutputStream dout = new DataOutputStream(bout);
+
+        try {
+            /*
+             * Write all the items of the "ClassFile" structure.
+             * See JVMS section 4.1.
+             */
+                                        // u4 magic;
+            dout.writeInt(0xCAFEBABE);
+                                        // u2 minor_version;
+            dout.writeShort(CLASSFILE_MINOR_VERSION);
+                                        // u2 major_version;
+            dout.writeShort(CLASSFILE_MAJOR_VERSION);
+
+            cp.write(dout);             // (write constant pool)
+
+                                        // u2 access_flags;
+            dout.writeShort(accessFlags);
+                                        // u2 this_class;
+            dout.writeShort(cp.getClass(dotToSlash(className)));
+                                        // u2 super_class;
+            dout.writeShort(cp.getClass(superclassName));
+
+                                        // u2 interfaces_count;
+            dout.writeShort(interfaces.length);
+                                        // u2 interfaces[interfaces_count];
+            for (Class<?> intf : interfaces) {
+                dout.writeShort(cp.getClass(
+                    dotToSlash(intf.getName())));
+            }
+
+                                        // u2 fields_count;
+            dout.writeShort(fields.size());
+                                        // field_info fields[fields_count];
+            for (FieldInfo f : fields) {
+                f.write(dout);
+            }
+
+                                        // u2 methods_count;
+            dout.writeShort(methods.size());
+                                        // method_info methods[methods_count];
+            for (MethodInfo m : methods) {
+                m.write(dout);
+            }
+
+                                         // u2 attributes_count;
+            dout.writeShort(0); // (no ClassFile attributes for proxy classes)
+
+        } catch (IOException e) {
+            throw new InternalError("unexpected I/O Exception", e);
+        }
+
+        return bout.toByteArray();
+    }
+
+    /**
+     * Add another method to be proxied, either by creating a new
+     * ProxyMethod object or augmenting an old one for a duplicate
+     * method.
+     *
+     * "fromClass" indicates the proxy interface that the method was
+     * found through, which may be different from (a subinterface of)
+     * the method's "declaring class".  Note that the first Method
+     * object passed for a given name and descriptor identifies the
+     * Method object (and thus the declaring class) that will be
+     * passed to the invocation handler's "invoke" method for a given
+     * set of duplicate methods.
+     */
+    private void addProxyMethod(Method m, Class<?> fromClass) {
+        String name = m.getName();
+        Class<?>[] parameterTypes = m.getParameterTypes();
+        Class<?> returnType = m.getReturnType();
+        Class<?>[] exceptionTypes = m.getExceptionTypes();
+
+        String sig = name + getParameterDescriptors(parameterTypes);
+        List<ProxyMethod> sigmethods = proxyMethods.get(sig);
+        if (sigmethods != null) {
+            for (ProxyMethod pm : sigmethods) {
+                if (returnType == pm.returnType) {
+                    /*
+                     * Found a match: reduce exception types to the
+                     * greatest set of exceptions that can thrown
+                     * compatibly with the throws clauses of both
+                     * overridden methods.
+                     */
+                    List<Class<?>> legalExceptions = new ArrayList<>();
+                    collectCompatibleTypes(
+                        exceptionTypes, pm.exceptionTypes, legalExceptions);
+                    collectCompatibleTypes(
+                        pm.exceptionTypes, exceptionTypes, legalExceptions);
+                    pm.exceptionTypes = new Class<?>[legalExceptions.size()];
+                    pm.exceptionTypes =
+                        legalExceptions.toArray(pm.exceptionTypes);
+                    return;
+                }
+            }
+        } else {
+            sigmethods = new ArrayList<>(3);
+            proxyMethods.put(sig, sigmethods);
+        }
+        sigmethods.add(new ProxyMethod(name, parameterTypes, returnType,
+                                       exceptionTypes, fromClass));
+    }
+
+    /**
+     * For a given set of proxy methods with the same signature, check
+     * that their return types are compatible according to the Proxy
+     * specification.
+     *
+     * Specifically, if there is more than one such method, then all
+     * of the return types must be reference types, and there must be
+     * one return type that is assignable to each of the rest of them.
+     */
+    private static void checkReturnTypes(List<ProxyMethod> methods) {
+        /*
+         * If there is only one method with a given signature, there
+         * cannot be a conflict.  This is the only case in which a
+         * primitive (or void) return type is allowed.
+         */
+        if (methods.size() < 2) {
+            return;
+        }
+
+        /*
+         * List of return types that are not yet known to be
+         * assignable from ("covered" by) any of the others.
+         */
+        LinkedList<Class<?>> uncoveredReturnTypes = new LinkedList<>();
+
+    nextNewReturnType:
+        for (ProxyMethod pm : methods) {
+            Class<?> newReturnType = pm.returnType;
+            if (newReturnType.isPrimitive()) {
+                throw new IllegalArgumentException(
+                    "methods with same signature " +
+                    getFriendlyMethodSignature(pm.methodName,
+                                               pm.parameterTypes) +
+                    " but incompatible return types: " +
+                    newReturnType.getName() + " and others");
+            }
+            boolean added = false;
+
+            /*
+             * Compare the new return type to the existing uncovered
+             * return types.
+             */
+            ListIterator<Class<?>> liter = uncoveredReturnTypes.listIterator();
+            while (liter.hasNext()) {
+                Class<?> uncoveredReturnType = liter.next();
+
+                /*
+                 * If an existing uncovered return type is assignable
+                 * to this new one, then we can forget the new one.
+                 */
+                if (newReturnType.isAssignableFrom(uncoveredReturnType)) {
+                    assert !added;
+                    continue nextNewReturnType;
+                }
+
+                /*
+                 * If the new return type is assignable to an existing
+                 * uncovered one, then should replace the existing one
+                 * with the new one (or just forget the existing one,
+                 * if the new one has already be put in the list).
+                 */
+                if (uncoveredReturnType.isAssignableFrom(newReturnType)) {
+                    // (we can assume that each return type is unique)
+                    if (!added) {
+                        liter.set(newReturnType);
+                        added = true;
+                    } else {
+                        liter.remove();
+                    }
+                }
+            }
+
+            /*
+             * If we got through the list of existing uncovered return
+             * types without an assignability relationship, then add
+             * the new return type to the list of uncovered ones.
+             */
+            if (!added) {
+                uncoveredReturnTypes.add(newReturnType);
+            }
+        }
+
+        /*
+         * We shouldn't end up with more than one return type that is
+         * not assignable from any of the others.
+         */
+        if (uncoveredReturnTypes.size() > 1) {
+            ProxyMethod pm = methods.get(0);
+            throw new IllegalArgumentException(
+                "methods with same signature " +
+                getFriendlyMethodSignature(pm.methodName, pm.parameterTypes) +
+                " but incompatible return types: " + uncoveredReturnTypes);
+        }
+    }
+
+    /**
+     * A FieldInfo object contains information about a particular field
+     * in the class being generated.  The class mirrors the data items of
+     * the "field_info" structure of the class file format (see JVMS 4.5).
+     */
+    private class FieldInfo {
+        public int accessFlags;
+        public String name;
+        public String descriptor;
+
+        public FieldInfo(String name, String descriptor, int accessFlags) {
+            this.name = name;
+            this.descriptor = descriptor;
+            this.accessFlags = accessFlags;
+
+            /*
+             * Make sure that constant pool indexes are reserved for the
+             * following items before starting to write the final class file.
+             */
+            cp.getUtf8(name);
+            cp.getUtf8(descriptor);
+        }
+
+        public void write(DataOutputStream out) throws IOException {
+            /*
+             * Write all the items of the "field_info" structure.
+             * See JVMS section 4.5.
+             */
+                                        // u2 access_flags;
+            out.writeShort(accessFlags);
+                                        // u2 name_index;
+            out.writeShort(cp.getUtf8(name));
+                                        // u2 descriptor_index;
+            out.writeShort(cp.getUtf8(descriptor));
+                                        // u2 attributes_count;
+            out.writeShort(0);  // (no field_info attributes for proxy classes)
+        }
+    }
+
+    /**
+     * An ExceptionTableEntry object holds values for the data items of
+     * an entry in the "exception_table" item of the "Code" attribute of
+     * "method_info" structures (see JVMS 4.7.3).
+     */
+    private static class ExceptionTableEntry {
+        public short startPc;
+        public short endPc;
+        public short handlerPc;
+        public short catchType;
+
+        public ExceptionTableEntry(short startPc, short endPc,
+                                   short handlerPc, short catchType)
+        {
+            this.startPc = startPc;
+            this.endPc = endPc;
+            this.handlerPc = handlerPc;
+            this.catchType = catchType;
+        }
+    };
+
+    /**
+     * A MethodInfo object contains information about a particular method
+     * in the class being generated.  This class mirrors the data items of
+     * the "method_info" structure of the class file format (see JVMS 4.6).
+     */
+    private class MethodInfo {
+        public int accessFlags;
+        public String name;
+        public String descriptor;
+        public short maxStack;
+        public short maxLocals;
+        public ByteArrayOutputStream code = new ByteArrayOutputStream();
+        public List<ExceptionTableEntry> exceptionTable =
+            new ArrayList<ExceptionTableEntry>();
+        public short[] declaredExceptions;
+
+        public MethodInfo(String name, String descriptor, int accessFlags) {
+            this.name = name;
+            this.descriptor = descriptor;
+            this.accessFlags = accessFlags;
+
+            /*
+             * Make sure that constant pool indexes are reserved for the
+             * following items before starting to write the final class file.
+             */
+            cp.getUtf8(name);
+            cp.getUtf8(descriptor);
+            cp.getUtf8("Code");
+            cp.getUtf8("Exceptions");
+        }
+
+        public void write(DataOutputStream out) throws IOException {
+            /*
+             * Write all the items of the "method_info" structure.
+             * See JVMS section 4.6.
+             */
+                                        // u2 access_flags;
+            out.writeShort(accessFlags);
+                                        // u2 name_index;
+            out.writeShort(cp.getUtf8(name));
+                                        // u2 descriptor_index;
+            out.writeShort(cp.getUtf8(descriptor));
+                                        // u2 attributes_count;
+            out.writeShort(2);  // (two method_info attributes:)
+
+            // Write "Code" attribute. See JVMS section 4.7.3.
+
+                                        // u2 attribute_name_index;
+            out.writeShort(cp.getUtf8("Code"));
+                                        // u4 attribute_length;
+            out.writeInt(12 + code.size() + 8 * exceptionTable.size());
+                                        // u2 max_stack;
+            out.writeShort(maxStack);
+                                        // u2 max_locals;
+            out.writeShort(maxLocals);
+                                        // u2 code_length;
+            out.writeInt(code.size());
+                                        // u1 code[code_length];
+            code.writeTo(out);
+                                        // u2 exception_table_length;
+            out.writeShort(exceptionTable.size());
+            for (ExceptionTableEntry e : exceptionTable) {
+                                        // u2 start_pc;
+                out.writeShort(e.startPc);
+                                        // u2 end_pc;
+                out.writeShort(e.endPc);
+                                        // u2 handler_pc;
+                out.writeShort(e.handlerPc);
+                                        // u2 catch_type;
+                out.writeShort(e.catchType);
+            }
+                                        // u2 attributes_count;
+            out.writeShort(0);
+
+            // write "Exceptions" attribute.  See JVMS section 4.7.4.
+
+                                        // u2 attribute_name_index;
+            out.writeShort(cp.getUtf8("Exceptions"));
+                                        // u4 attributes_length;
+            out.writeInt(2 + 2 * declaredExceptions.length);
+                                        // u2 number_of_exceptions;
+            out.writeShort(declaredExceptions.length);
+                        // u2 exception_index_table[number_of_exceptions];
+            for (short value : declaredExceptions) {
+                out.writeShort(value);
+            }
+        }
+
+    }
+
+    /**
+     * A ProxyMethod object represents a proxy method in the proxy class
+     * being generated: a method whose implementation will encode and
+     * dispatch invocations to the proxy instance's invocation handler.
+     */
+    private class ProxyMethod {
+
+        public String methodName;
+        public Class<?>[] parameterTypes;
+        public Class<?> returnType;
+        public Class<?>[] exceptionTypes;
+        public Class<?> fromClass;
+        public String methodFieldName;
+
+        private ProxyMethod(String methodName, Class<?>[] parameterTypes,
+                            Class<?> returnType, Class<?>[] exceptionTypes,
+                            Class<?> fromClass)
+        {
+            this.methodName = methodName;
+            this.parameterTypes = parameterTypes;
+            this.returnType = returnType;
+            this.exceptionTypes = exceptionTypes;
+            this.fromClass = fromClass;
+            this.methodFieldName = "m" + proxyMethodCount++;
+        }
+
+        /**
+         * Return a MethodInfo object for this method, including generating
+         * the code and exception table entry.
+         */
+        private MethodInfo generateMethod() throws IOException {
+            String desc = getMethodDescriptor(parameterTypes, returnType);
+            MethodInfo minfo = new MethodInfo(methodName, desc,
+                ACC_PUBLIC | ACC_FINAL);
+
+            int[] parameterSlot = new int[parameterTypes.length];
+            int nextSlot = 1;
+            for (int i = 0; i < parameterSlot.length; i++) {
+                parameterSlot[i] = nextSlot;
+                nextSlot += getWordsPerType(parameterTypes[i]);
+            }
+            int localSlot0 = nextSlot;
+            short pc, tryBegin = 0, tryEnd;
+
+            DataOutputStream out = new DataOutputStream(minfo.code);
+
+            code_aload(0, out);
+
+            out.writeByte(opc_getfield);
+            out.writeShort(cp.getFieldRef(
+                superclassName,
+                handlerFieldName, "Ljava/lang/reflect/InvocationHandler;"));
+
+            code_aload(0, out);
+
+            out.writeByte(opc_getstatic);
+            out.writeShort(cp.getFieldRef(
+                dotToSlash(className),
+                methodFieldName, "Ljava/lang/reflect/Method;"));
+
+            if (parameterTypes.length > 0) {
+
+                code_ipush(parameterTypes.length, out);
+
+                out.writeByte(opc_anewarray);
+                out.writeShort(cp.getClass("java/lang/Object"));
+
+                for (int i = 0; i < parameterTypes.length; i++) {
+
+                    out.writeByte(opc_dup);
+
+                    code_ipush(i, out);
+
+                    codeWrapArgument(parameterTypes[i], parameterSlot[i], out);
+
+                    out.writeByte(opc_aastore);
+                }
+            } else {
+
+                out.writeByte(opc_aconst_null);
+            }
+
+            out.writeByte(opc_invokeinterface);
+            out.writeShort(cp.getInterfaceMethodRef(
+                "java/lang/reflect/InvocationHandler",
+                "invoke",
+                "(Ljava/lang/Object;Ljava/lang/reflect/Method;" +
+                    "[Ljava/lang/Object;)Ljava/lang/Object;"));
+            out.writeByte(4);
+            out.writeByte(0);
+
+            if (returnType == void.class) {
+
+                out.writeByte(opc_pop);
+
+                out.writeByte(opc_return);
+
+            } else {
+
+                codeUnwrapReturnValue(returnType, out);
+            }
+
+            tryEnd = pc = (short) minfo.code.size();
+
+            List<Class<?>> catchList = computeUniqueCatchList(exceptionTypes);
+            if (catchList.size() > 0) {
+
+                for (Class<?> ex : catchList) {
+                    minfo.exceptionTable.add(new ExceptionTableEntry(
+                        tryBegin, tryEnd, pc,
+                        cp.getClass(dotToSlash(ex.getName()))));
+                }
+
+                out.writeByte(opc_athrow);
+
+                pc = (short) minfo.code.size();
+
+                minfo.exceptionTable.add(new ExceptionTableEntry(
+                    tryBegin, tryEnd, pc, cp.getClass("java/lang/Throwable")));
+
+                code_astore(localSlot0, out);
+
+                out.writeByte(opc_new);
+                out.writeShort(cp.getClass(
+                    "java/lang/reflect/UndeclaredThrowableException"));
+
+                out.writeByte(opc_dup);
+
+                code_aload(localSlot0, out);
+
+                out.writeByte(opc_invokespecial);
+
+                out.writeShort(cp.getMethodRef(
+                    "java/lang/reflect/UndeclaredThrowableException",
+                    "<init>", "(Ljava/lang/Throwable;)V"));
+
+                out.writeByte(opc_athrow);
+            }
+
+            if (minfo.code.size() > 65535) {
+                throw new IllegalArgumentException("code size limit exceeded");
+            }
+
+            minfo.maxStack = 10;
+            minfo.maxLocals = (short) (localSlot0 + 1);
+            minfo.declaredExceptions = new short[exceptionTypes.length];
+            for (int i = 0; i < exceptionTypes.length; i++) {
+                minfo.declaredExceptions[i] = cp.getClass(
+                    dotToSlash(exceptionTypes[i].getName()));
+            }
+
+            return minfo;
+        }
+
+        /**
+         * Generate code for wrapping an argument of the given type
+         * whose value can be found at the specified local variable
+         * index, in order for it to be passed (as an Object) to the
+         * invocation handler's "invoke" method.  The code is written
+         * to the supplied stream.
+         */
+        private void codeWrapArgument(Class<?> type, int slot,
+                                      DataOutputStream out)
+            throws IOException
+        {
+            if (type.isPrimitive()) {
+                PrimitiveTypeInfo prim = PrimitiveTypeInfo.get(type);
+
+                if (type == int.class ||
+                    type == boolean.class ||
+                    type == byte.class ||
+                    type == char.class ||
+                    type == short.class)
+                {
+                    code_iload(slot, out);
+                } else if (type == long.class) {
+                    code_lload(slot, out);
+                } else if (type == float.class) {
+                    code_fload(slot, out);
+                } else if (type == double.class) {
+                    code_dload(slot, out);
+                } else {
+                    throw new AssertionError();
+                }
+
+                out.writeByte(opc_invokestatic);
+                out.writeShort(cp.getMethodRef(
+                    prim.wrapperClassName,
+                    "valueOf", prim.wrapperValueOfDesc));
+
+            } else {
+
+                code_aload(slot, out);
+            }
+        }
+
+        /**
+         * Generate code for unwrapping a return value of the given
+         * type from the invocation handler's "invoke" method (as type
+         * Object) to its correct type.  The code is written to the
+         * supplied stream.
+         */
+        private void codeUnwrapReturnValue(Class<?> type, DataOutputStream out)
+            throws IOException
+        {
+            if (type.isPrimitive()) {
+                PrimitiveTypeInfo prim = PrimitiveTypeInfo.get(type);
+
+                out.writeByte(opc_checkcast);
+                out.writeShort(cp.getClass(prim.wrapperClassName));
+
+                out.writeByte(opc_invokevirtual);
+                out.writeShort(cp.getMethodRef(
+                    prim.wrapperClassName,
+                    prim.unwrapMethodName, prim.unwrapMethodDesc));
+
+                if (type == int.class ||
+                    type == boolean.class ||
+                    type == byte.class ||
+                    type == char.class ||
+                    type == short.class)
+                {
+                    out.writeByte(opc_ireturn);
+                } else if (type == long.class) {
+                    out.writeByte(opc_lreturn);
+                } else if (type == float.class) {
+                    out.writeByte(opc_freturn);
+                } else if (type == double.class) {
+                    out.writeByte(opc_dreturn);
+                } else {
+                    throw new AssertionError();
+                }
+
+            } else {
+
+                out.writeByte(opc_checkcast);
+                out.writeShort(cp.getClass(dotToSlash(type.getName())));
+
+                out.writeByte(opc_areturn);
+            }
+        }
+
+        /**
+         * Generate code for initializing the static field that stores
+         * the Method object for this proxy method.  The code is written
+         * to the supplied stream.
+         */
+        private void codeFieldInitialization(DataOutputStream out)
+            throws IOException
+        {
+            codeClassForName(fromClass, out);
+
+            code_ldc(cp.getString(methodName), out);
+
+            code_ipush(parameterTypes.length, out);
+
+            out.writeByte(opc_anewarray);
+            out.writeShort(cp.getClass("java/lang/Class"));
+
+            for (int i = 0; i < parameterTypes.length; i++) {
+
+                out.writeByte(opc_dup);
+
+                code_ipush(i, out);
+
+                if (parameterTypes[i].isPrimitive()) {
+                    PrimitiveTypeInfo prim =
+                        PrimitiveTypeInfo.get(parameterTypes[i]);
+
+                    out.writeByte(opc_getstatic);
+                    out.writeShort(cp.getFieldRef(
+                        prim.wrapperClassName, "TYPE", "Ljava/lang/Class;"));
+
+                } else {
+                    codeClassForName(parameterTypes[i], out);
+                }
+
+                out.writeByte(opc_aastore);
+            }
+
+            out.writeByte(opc_invokevirtual);
+            out.writeShort(cp.getMethodRef(
+                "java/lang/Class",
+                "getMethod",
+                "(Ljava/lang/String;[Ljava/lang/Class;)" +
+                "Ljava/lang/reflect/Method;"));
+
+            out.writeByte(opc_putstatic);
+            out.writeShort(cp.getFieldRef(
+                dotToSlash(className),
+                methodFieldName, "Ljava/lang/reflect/Method;"));
+        }
+    }
+
+    /**
+     * Generate the constructor method for the proxy class.
+     */
+    private MethodInfo generateConstructor() throws IOException {
+        MethodInfo minfo = new MethodInfo(
+            "<init>", "(Ljava/lang/reflect/InvocationHandler;)V",
+            ACC_PUBLIC);
+
+        DataOutputStream out = new DataOutputStream(minfo.code);
+
+        code_aload(0, out);
+
+        code_aload(1, out);
+
+        out.writeByte(opc_invokespecial);
+        out.writeShort(cp.getMethodRef(
+            superclassName,
+            "<init>", "(Ljava/lang/reflect/InvocationHandler;)V"));
+
+        out.writeByte(opc_return);
+
+        minfo.maxStack = 10;
+        minfo.maxLocals = 2;
+        minfo.declaredExceptions = new short[0];
+
+        return minfo;
+    }
+
+    /**
+     * Generate the static initializer method for the proxy class.
+     */
+    private MethodInfo generateStaticInitializer() throws IOException {
+        MethodInfo minfo = new MethodInfo(
+            "<clinit>", "()V", ACC_STATIC);
+
+        int localSlot0 = 1;
+        short pc, tryBegin = 0, tryEnd;
+
+        DataOutputStream out = new DataOutputStream(minfo.code);
+
+        for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
+            for (ProxyMethod pm : sigmethods) {
+                pm.codeFieldInitialization(out);
+            }
+        }
+
+        out.writeByte(opc_return);
+
+        tryEnd = pc = (short) minfo.code.size();
+
+        minfo.exceptionTable.add(new ExceptionTableEntry(
+            tryBegin, tryEnd, pc,
+            cp.getClass("java/lang/NoSuchMethodException")));
+
+        code_astore(localSlot0, out);
+
+        out.writeByte(opc_new);
+        out.writeShort(cp.getClass("java/lang/NoSuchMethodError"));
+
+        out.writeByte(opc_dup);
+
+        code_aload(localSlot0, out);
+
+        out.writeByte(opc_invokevirtual);
+        out.writeShort(cp.getMethodRef(
+            "java/lang/Throwable", "getMessage", "()Ljava/lang/String;"));
+
+        out.writeByte(opc_invokespecial);
+        out.writeShort(cp.getMethodRef(
+            "java/lang/NoSuchMethodError", "<init>", "(Ljava/lang/String;)V"));
+
+        out.writeByte(opc_athrow);
+
+        pc = (short) minfo.code.size();
+
+        minfo.exceptionTable.add(new ExceptionTableEntry(
+            tryBegin, tryEnd, pc,
+            cp.getClass("java/lang/ClassNotFoundException")));
+
+        code_astore(localSlot0, out);
+
+        out.writeByte(opc_new);
+        out.writeShort(cp.getClass("java/lang/NoClassDefFoundError"));
+
+        out.writeByte(opc_dup);
+
+        code_aload(localSlot0, out);
+
+        out.writeByte(opc_invokevirtual);
+        out.writeShort(cp.getMethodRef(
+            "java/lang/Throwable", "getMessage", "()Ljava/lang/String;"));
+
+        out.writeByte(opc_invokespecial);
+        out.writeShort(cp.getMethodRef(
+            "java/lang/NoClassDefFoundError",
+            "<init>", "(Ljava/lang/String;)V"));
+
+        out.writeByte(opc_athrow);
+
+        if (minfo.code.size() > 65535) {
+            throw new IllegalArgumentException("code size limit exceeded");
+        }
+
+        minfo.maxStack = 10;
+        minfo.maxLocals = (short) (localSlot0 + 1);
+        minfo.declaredExceptions = new short[0];
+
+        return minfo;
+    }
+
+
+    /*
+     * =============== Code Generation Utility Methods ===============
+     */
+
+    /*
+     * The following methods generate code for the load or store operation
+     * indicated by their name for the given local variable.  The code is
+     * written to the supplied stream.
+     */
+
+    private void code_iload(int lvar, DataOutputStream out)
+        throws IOException
+    {
+        codeLocalLoadStore(lvar, opc_iload, opc_iload_0, out);
+    }
+
+    private void code_lload(int lvar, DataOutputStream out)
+        throws IOException
+    {
+        codeLocalLoadStore(lvar, opc_lload, opc_lload_0, out);
+    }
+
+    private void code_fload(int lvar, DataOutputStream out)
+        throws IOException
+    {
+        codeLocalLoadStore(lvar, opc_fload, opc_fload_0, out);
+    }
+
+    private void code_dload(int lvar, DataOutputStream out)
+        throws IOException
+    {
+        codeLocalLoadStore(lvar, opc_dload, opc_dload_0, out);
+    }
+
+    private void code_aload(int lvar, DataOutputStream out)
+        throws IOException
+    {
+        codeLocalLoadStore(lvar, opc_aload, opc_aload_0, out);
+    }
+
+//  private void code_istore(int lvar, DataOutputStream out)
+//      throws IOException
+//  {
+//      codeLocalLoadStore(lvar, opc_istore, opc_istore_0, out);
+//  }
+
+//  private void code_lstore(int lvar, DataOutputStream out)
+//      throws IOException
+//  {
+//      codeLocalLoadStore(lvar, opc_lstore, opc_lstore_0, out);
+//  }
+
+//  private void code_fstore(int lvar, DataOutputStream out)
+//      throws IOException
+//  {
+//      codeLocalLoadStore(lvar, opc_fstore, opc_fstore_0, out);
+//  }
+
+//  private void code_dstore(int lvar, DataOutputStream out)
+//      throws IOException
+//  {
+//      codeLocalLoadStore(lvar, opc_dstore, opc_dstore_0, out);
+//  }
+
+    private void code_astore(int lvar, DataOutputStream out)
+        throws IOException
+    {
+        codeLocalLoadStore(lvar, opc_astore, opc_astore_0, out);
+    }
+
+    /**
+     * Generate code for a load or store instruction for the given local
+     * variable.  The code is written to the supplied stream.
+     *
+     * "opcode" indicates the opcode form of the desired load or store
+     * instruction that takes an explicit local variable index, and
+     * "opcode_0" indicates the corresponding form of the instruction
+     * with the implicit index 0.
+     */
+    private void codeLocalLoadStore(int lvar, int opcode, int opcode_0,
+                                    DataOutputStream out)
+        throws IOException
+    {
+        assert lvar >= 0 && lvar <= 0xFFFF;
+        if (lvar <= 3) {
+            out.writeByte(opcode_0 + lvar);
+        } else if (lvar <= 0xFF) {
+            out.writeByte(opcode);
+            out.writeByte(lvar & 0xFF);
+        } else {
+            /*
+             * Use the "wide" instruction modifier for local variable
+             * indexes that do not fit into an unsigned byte.
+             */
+            out.writeByte(opc_wide);
+            out.writeByte(opcode);
+            out.writeShort(lvar & 0xFFFF);
+        }
+    }
+
+    /**
+     * Generate code for an "ldc" instruction for the given constant pool
+     * index (the "ldc_w" instruction is used if the index does not fit
+     * into an unsigned byte).  The code is written to the supplied stream.
+     */
+    private void code_ldc(int index, DataOutputStream out)
+        throws IOException
+    {
+        assert index >= 0 && index <= 0xFFFF;
+        if (index <= 0xFF) {
+            out.writeByte(opc_ldc);
+            out.writeByte(index & 0xFF);
+        } else {
+            out.writeByte(opc_ldc_w);
+            out.writeShort(index & 0xFFFF);
+        }
+    }
+
+    /**
+     * Generate code to push a constant integer value on to the operand
+     * stack, using the "iconst_<i>", "bipush", or "sipush" instructions
+     * depending on the size of the value.  The code is written to the
+     * supplied stream.
+     */
+    private void code_ipush(int value, DataOutputStream out)
+        throws IOException
+    {
+        if (value >= -1 && value <= 5) {
+            out.writeByte(opc_iconst_0 + value);
+        } else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) {
+            out.writeByte(opc_bipush);
+            out.writeByte(value & 0xFF);
+        } else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) {
+            out.writeByte(opc_sipush);
+            out.writeShort(value & 0xFFFF);
+        } else {
+            throw new AssertionError();
+        }
+    }
+
+    /**
+     * Generate code to invoke the Class.forName with the name of the given
+     * class to get its Class object at runtime.  The code is written to
+     * the supplied stream.  Note that the code generated by this method
+     * may caused the checked ClassNotFoundException to be thrown.
+     */
+    private void codeClassForName(Class<?> cl, DataOutputStream out)
+        throws IOException
+    {
+        code_ldc(cp.getString(cl.getName()), out);
+
+        out.writeByte(opc_invokestatic);
+        out.writeShort(cp.getMethodRef(
+            "java/lang/Class",
+            "forName", "(Ljava/lang/String;)Ljava/lang/Class;"));
+    }
+
+
+    /*
+     * ==================== General Utility Methods ====================
+     */
+
+    /**
+     * Convert a fully qualified class name that uses '.' as the package
+     * separator, the external representation used by the Java language
+     * and APIs, to a fully qualified class name that uses '/' as the
+     * package separator, the representation used in the class file
+     * format (see JVMS section 4.2).
+     */
+    private static String dotToSlash(String name) {
+        return name.replace('.', '/');
+    }
+
+    /**
+     * Return the "method descriptor" string for a method with the given
+     * parameter types and return type.  See JVMS section 4.3.3.
+     */
+    private static String getMethodDescriptor(Class<?>[] parameterTypes,
+                                              Class<?> returnType)
+    {
+        return getParameterDescriptors(parameterTypes) +
+            ((returnType == void.class) ? "V" : getFieldType(returnType));
+    }
+
+    /**
+     * Return the list of "parameter descriptor" strings enclosed in
+     * parentheses corresponding to the given parameter types (in other
+     * words, a method descriptor without a return descriptor).  This
+     * string is useful for constructing string keys for methods without
+     * regard to their return type.
+     */
+    private static String getParameterDescriptors(Class<?>[] parameterTypes) {
+        StringBuilder desc = new StringBuilder("(");
+        for (int i = 0; i < parameterTypes.length; i++) {
+            desc.append(getFieldType(parameterTypes[i]));
+        }
+        desc.append(')');
+        return desc.toString();
+    }
+
+    /**
+     * Return the "field type" string for the given type, appropriate for
+     * a field descriptor, a parameter descriptor, or a return descriptor
+     * other than "void".  See JVMS section 4.3.2.
+     */
+    private static String getFieldType(Class<?> type) {
+        if (type.isPrimitive()) {
+            return PrimitiveTypeInfo.get(type).baseTypeString;
+        } else if (type.isArray()) {
+            /*
+             * According to JLS 20.3.2, the getName() method on Class does
+             * return the VM type descriptor format for array classes (only);
+             * using that should be quicker than the otherwise obvious code:
+             *
+             *     return "[" + getTypeDescriptor(type.getComponentType());
+             */
+            return type.getName().replace('.', '/');
+        } else {
+            return "L" + dotToSlash(type.getName()) + ";";
+        }
+    }
+
+    /**
+     * Returns a human-readable string representing the signature of a
+     * method with the given name and parameter types.
+     */
+    private static String getFriendlyMethodSignature(String name,
+                                                     Class<?>[] parameterTypes)
+    {
+        StringBuilder sig = new StringBuilder(name);
+        sig.append('(');
+        for (int i = 0; i < parameterTypes.length; i++) {
+            if (i > 0) {
+                sig.append(',');
+            }
+            Class<?> parameterType = parameterTypes[i];
+            int dimensions = 0;
+            while (parameterType.isArray()) {
+                parameterType = parameterType.getComponentType();
+                dimensions++;
+            }
+            sig.append(parameterType.getName());
+            while (dimensions-- > 0) {
+                sig.append("[]");
+            }
+        }
+        sig.append(')');
+        return sig.toString();
+    }
+
+    /**
+     * Return the number of abstract "words", or consecutive local variable
+     * indexes, required to contain a value of the given type.  See JVMS
+     * section 3.6.1.
+     *
+     * Note that the original version of the JVMS contained a definition of
+     * this abstract notion of a "word" in section 3.4, but that definition
+     * was removed for the second edition.
+     */
+    private static int getWordsPerType(Class<?> type) {
+        if (type == long.class || type == double.class) {
+            return 2;
+        } else {
+            return 1;
+        }
+    }
+
+    /**
+     * Add to the given list all of the types in the "from" array that
+     * are not already contained in the list and are assignable to at
+     * least one of the types in the "with" array.
+     *
+     * This method is useful for computing the greatest common set of
+     * declared exceptions from duplicate methods inherited from
+     * different interfaces.
+     */
+    private static void collectCompatibleTypes(Class<?>[] from,
+                                               Class<?>[] with,
+                                               List<Class<?>> list)
+    {
+        for (Class<?> fc: from) {
+            if (!list.contains(fc)) {
+                for (Class<?> wc: with) {
+                    if (wc.isAssignableFrom(fc)) {
+                        list.add(fc);
+                        break;
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Given the exceptions declared in the throws clause of a proxy method,
+     * compute the exceptions that need to be caught from the invocation
+     * handler's invoke method and rethrown intact in the method's
+     * implementation before catching other Throwables and wrapping them
+     * in UndeclaredThrowableExceptions.
+     *
+     * The exceptions to be caught are returned in a List object.  Each
+     * exception in the returned list is guaranteed to not be a subclass of
+     * any of the other exceptions in the list, so the catch blocks for
+     * these exceptions may be generated in any order relative to each other.
+     *
+     * Error and RuntimeException are each always contained by the returned
+     * list (if none of their superclasses are contained), since those
+     * unchecked exceptions should always be rethrown intact, and thus their
+     * subclasses will never appear in the returned list.
+     *
+     * The returned List will be empty if java.lang.Throwable is in the
+     * given list of declared exceptions, indicating that no exceptions
+     * need to be caught.
+     */
+    private static List<Class<?>> computeUniqueCatchList(Class<?>[] exceptions) {
+        List<Class<?>> uniqueList = new ArrayList<>();
+                                                // unique exceptions to catch
+
+        uniqueList.add(Error.class);            // always catch/rethrow these
+        uniqueList.add(RuntimeException.class);
+
+    nextException:
+        for (Class<?> ex: exceptions) {
+            if (ex.isAssignableFrom(Throwable.class)) {
+                /*
+                 * If Throwable is declared to be thrown by the proxy method,
+                 * then no catch blocks are necessary, because the invoke
+                 * can, at most, throw Throwable anyway.
+                 */
+                uniqueList.clear();
+                break;
+            } else if (!Throwable.class.isAssignableFrom(ex)) {
+                /*
+                 * Ignore types that cannot be thrown by the invoke method.
+                 */
+                continue;
+            }
+            /*
+             * Compare this exception against the current list of
+             * exceptions that need to be caught:
+             */
+            for (int j = 0; j < uniqueList.size();) {
+                Class<?> ex2 = uniqueList.get(j);
+                if (ex2.isAssignableFrom(ex)) {
+                    /*
+                     * if a superclass of this exception is already on
+                     * the list to catch, then ignore this one and continue;
+                     */
+                    continue nextException;
+                } else if (ex.isAssignableFrom(ex2)) {
+                    /*
+                     * if a subclass of this exception is on the list
+                     * to catch, then remove it;
+                     */
+                    uniqueList.remove(j);
+                } else {
+                    j++;        // else continue comparing.
+                }
+            }
+            // This exception is unique (so far): add it to the list to catch.
+            uniqueList.add(ex);
+        }
+        return uniqueList;
+    }
+
+    /**
+     * A PrimitiveTypeInfo object contains assorted information about
+     * a primitive type in its public fields.  The struct for a particular
+     * primitive type can be obtained using the static "get" method.
+     */
+    private static class PrimitiveTypeInfo {
+
+        /** "base type" used in various descriptors (see JVMS section 4.3.2) */
+        public String baseTypeString;
+
+        /** name of corresponding wrapper class */
+        public String wrapperClassName;
+
+        /** method descriptor for wrapper class "valueOf" factory method */
+        public String wrapperValueOfDesc;
+
+        /** name of wrapper class method for retrieving primitive value */
+        public String unwrapMethodName;
+
+        /** descriptor of same method */
+        public String unwrapMethodDesc;
+
+        private static Map<Class<?>,PrimitiveTypeInfo> table = new HashMap<>();
+        static {
+            add(byte.class, Byte.class);
+            add(char.class, Character.class);
+            add(double.class, Double.class);
+            add(float.class, Float.class);
+            add(int.class, Integer.class);
+            add(long.class, Long.class);
+            add(short.class, Short.class);
+            add(boolean.class, Boolean.class);
+        }
+
+        private static void add(Class<?> primitiveClass, Class<?> wrapperClass) {
+            table.put(primitiveClass,
+                      new PrimitiveTypeInfo(primitiveClass, wrapperClass));
+        }
+
+        private PrimitiveTypeInfo(Class<?> primitiveClass, Class<?> wrapperClass) {
+            assert primitiveClass.isPrimitive();
+
+            baseTypeString =
+                Array.newInstance(primitiveClass, 0)
+                .getClass().getName().substring(1);
+            wrapperClassName = dotToSlash(wrapperClass.getName());
+            wrapperValueOfDesc =
+                "(" + baseTypeString + ")L" + wrapperClassName + ";";
+            unwrapMethodName = primitiveClass.getName() + "Value";
+            unwrapMethodDesc = "()" + baseTypeString;
+        }
+
+        public static PrimitiveTypeInfo get(Class<?> cl) {
+            return table.get(cl);
+        }
+    }
+
+
+    /**
+     * A ConstantPool object represents the constant pool of a class file
+     * being generated.  This representation of a constant pool is designed
+     * specifically for use by ProxyGenerator; in particular, it assumes
+     * that constant pool entries will not need to be resorted (for example,
+     * by their type, as the Java compiler does), so that the final index
+     * value can be assigned and used when an entry is first created.
+     *
+     * Note that new entries cannot be created after the constant pool has
+     * been written to a class file.  To prevent such logic errors, a
+     * ConstantPool instance can be marked "read only", so that further
+     * attempts to add new entries will fail with a runtime exception.
+     *
+     * See JVMS section 4.4 for more information about the constant pool
+     * of a class file.
+     */
+    private static class ConstantPool {
+
+        /**
+         * list of constant pool entries, in constant pool index order.
+         *
+         * This list is used when writing the constant pool to a stream
+         * and for assigning the next index value.  Note that element 0
+         * of this list corresponds to constant pool index 1.
+         */
+        private List<Entry> pool = new ArrayList<>(32);
+
+        /**
+         * maps constant pool data of all types to constant pool indexes.
+         *
+         * This map is used to look up the index of an existing entry for
+         * values of all types.
+         */
+        private Map<Object,Short> map = new HashMap<>(16);
+
+        /** true if no new constant pool entries may be added */
+        private boolean readOnly = false;
+
+        /**
+         * Get or assign the index for a CONSTANT_Utf8 entry.
+         */
+        public short getUtf8(String s) {
+            if (s == null) {
+                throw new NullPointerException();
+            }
+            return getValue(s);
+        }
+
+        /**
+         * Get or assign the index for a CONSTANT_Integer entry.
+         */
+        public short getInteger(int i) {
+            return getValue(i);
+        }
+
+        /**
+         * Get or assign the index for a CONSTANT_Float entry.
+         */
+        public short getFloat(float f) {
+            return getValue(new Float(f));
+        }
+
+        /**
+         * Get or assign the index for a CONSTANT_Class entry.
+         */
+        public short getClass(String name) {
+            short utf8Index = getUtf8(name);
+            return getIndirect(new IndirectEntry(
+                CONSTANT_CLASS, utf8Index));
+        }
+
+        /**
+         * Get or assign the index for a CONSTANT_String entry.
+         */
+        public short getString(String s) {
+            short utf8Index = getUtf8(s);
+            return getIndirect(new IndirectEntry(
+                CONSTANT_STRING, utf8Index));
+        }
+
+        /**
+         * Get or assign the index for a CONSTANT_FieldRef entry.
+         */
+        public short getFieldRef(String className,
+                                 String name, String descriptor)
+        {
+            short classIndex = getClass(className);
+            short nameAndTypeIndex = getNameAndType(name, descriptor);
+            return getIndirect(new IndirectEntry(
+                CONSTANT_FIELD, classIndex, nameAndTypeIndex));
+        }
+
+        /**
+         * Get or assign the index for a CONSTANT_MethodRef entry.
+         */
+        public short getMethodRef(String className,
+                                  String name, String descriptor)
+        {
+            short classIndex = getClass(className);
+            short nameAndTypeIndex = getNameAndType(name, descriptor);
+            return getIndirect(new IndirectEntry(
+                CONSTANT_METHOD, classIndex, nameAndTypeIndex));
+        }
+
+        /**
+         * Get or assign the index for a CONSTANT_InterfaceMethodRef entry.
+         */
+        public short getInterfaceMethodRef(String className, String name,
+                                           String descriptor)
+        {
+            short classIndex = getClass(className);
+            short nameAndTypeIndex = getNameAndType(name, descriptor);
+            return getIndirect(new IndirectEntry(
+                CONSTANT_INTERFACEMETHOD, classIndex, nameAndTypeIndex));
+        }
+
+        /**
+         * Get or assign the index for a CONSTANT_NameAndType entry.
+         */
+        public short getNameAndType(String name, String descriptor) {
+            short nameIndex = getUtf8(name);
+            short descriptorIndex = getUtf8(descriptor);
+            return getIndirect(new IndirectEntry(
+                CONSTANT_NAMEANDTYPE, nameIndex, descriptorIndex));
+        }
+
+        /**
+         * Set this ConstantPool instance to be "read only".
+         *
+         * After this method has been called, further requests to get
+         * an index for a non-existent entry will cause an InternalError
+         * to be thrown instead of creating of the entry.
+         */
+        public void setReadOnly() {
+            readOnly = true;
+        }
+
+        /**
+         * Write this constant pool to a stream as part of
+         * the class file format.
+         *
+         * This consists of writing the "constant_pool_count" and
+         * "constant_pool[]" items of the "ClassFile" structure, as
+         * described in JVMS section 4.1.
+         */
+        public void write(OutputStream out) throws IOException {
+            DataOutputStream dataOut = new DataOutputStream(out);
+
+            // constant_pool_count: number of entries plus one
+            dataOut.writeShort(pool.size() + 1);
+
+            for (Entry e : pool) {
+                e.write(dataOut);
+            }
+        }
+
+        /**
+         * Add a new constant pool entry and return its index.
+         */
+        private short addEntry(Entry entry) {
+            pool.add(entry);
+            /*
+             * Note that this way of determining the index of the
+             * added entry is wrong if this pool supports
+             * CONSTANT_Long or CONSTANT_Double entries.
+             */
+            if (pool.size() >= 65535) {
+                throw new IllegalArgumentException(
+                    "constant pool size limit exceeded");
+            }
+            return (short) pool.size();
+        }
+
+        /**
+         * Get or assign the index for an entry of a type that contains
+         * a direct value.  The type of the given object determines the
+         * type of the desired entry as follows:
+         *
+         *      java.lang.String        CONSTANT_Utf8
+         *      java.lang.Integer       CONSTANT_Integer
+         *      java.lang.Float         CONSTANT_Float
+         *      java.lang.Long          CONSTANT_Long
+         *      java.lang.Double        CONSTANT_DOUBLE
+         */
+        private short getValue(Object key) {
+            Short index = map.get(key);
+            if (index != null) {
+                return index.shortValue();
+            } else {
+                if (readOnly) {
+                    throw new InternalError(
+                        "late constant pool addition: " + key);
+                }
+                short i = addEntry(new ValueEntry(key));
+                map.put(key, i);
+                return i;
+            }
+        }
+
+        /**
+         * Get or assign the index for an entry of a type that contains
+         * references to other constant pool entries.
+         */
+        private short getIndirect(IndirectEntry e) {
+            Short index = map.get(e);
+            if (index != null) {
+                return index.shortValue();
+            } else {
+                if (readOnly) {
+                    throw new InternalError("late constant pool addition");
+                }
+                short i = addEntry(e);
+                map.put(e, i);
+                return i;
+            }
+        }
+
+        /**
+         * Entry is the abstact superclass of all constant pool entry types
+         * that can be stored in the "pool" list; its purpose is to define a
+         * common method for writing constant pool entries to a class file.
+         */
+        private abstract static class Entry {
+            public abstract void write(DataOutputStream out)
+                throws IOException;
+        }
+
+        /**
+         * ValueEntry represents a constant pool entry of a type that
+         * contains a direct value (see the comments for the "getValue"
+         * method for a list of such types).
+         *
+         * ValueEntry objects are not used as keys for their entries in the
+         * Map "map", so no useful hashCode or equals methods are defined.
+         */
+        private static class ValueEntry extends Entry {
+            private Object value;
+
+            public ValueEntry(Object value) {
+                this.value = value;
+            }
+
+            public void write(DataOutputStream out) throws IOException {
+                if (value instanceof String) {
+                    out.writeByte(CONSTANT_UTF8);
+                    out.writeUTF((String) value);
+                } else if (value instanceof Integer) {
+                    out.writeByte(CONSTANT_INTEGER);
+                    out.writeInt(((Integer) value).intValue());
+                } else if (value instanceof Float) {
+                    out.writeByte(CONSTANT_FLOAT);
+                    out.writeFloat(((Float) value).floatValue());
+                } else if (value instanceof Long) {
+                    out.writeByte(CONSTANT_LONG);
+                    out.writeLong(((Long) value).longValue());
+                } else if (value instanceof Double) {
+                    out.writeDouble(CONSTANT_DOUBLE);
+                    out.writeDouble(((Double) value).doubleValue());
+                } else {
+                    throw new InternalError("bogus value entry: " + value);
+                }
+            }
+        }
+
+        /**
+         * IndirectEntry represents a constant pool entry of a type that
+         * references other constant pool entries, i.e., the following types:
+         *
+         *      CONSTANT_Class, CONSTANT_String, CONSTANT_Fieldref,
+         *      CONSTANT_Methodref, CONSTANT_InterfaceMethodref, and
+         *      CONSTANT_NameAndType.
+         *
+         * Each of these entry types contains either one or two indexes of
+         * other constant pool entries.
+         *
+         * IndirectEntry objects are used as the keys for their entries in
+         * the Map "map", so the hashCode and equals methods are overridden
+         * to allow matching.
+         */
+        private static class IndirectEntry extends Entry {
+            private int tag;
+            private short index0;
+            private short index1;
+
+            /**
+             * Construct an IndirectEntry for a constant pool entry type
+             * that contains one index of another entry.
+             */
+            public IndirectEntry(int tag, short index) {
+                this.tag = tag;
+                this.index0 = index;
+                this.index1 = 0;
+            }
+
+            /**
+             * Construct an IndirectEntry for a constant pool entry type
+             * that contains two indexes for other entries.
+             */
+            public IndirectEntry(int tag, short index0, short index1) {
+                this.tag = tag;
+                this.index0 = index0;
+                this.index1 = index1;
+            }
+
+            public void write(DataOutputStream out) throws IOException {
+                out.writeByte(tag);
+                out.writeShort(index0);
+                /*
+                 * If this entry type contains two indexes, write
+                 * out the second, too.
+                 */
+                if (tag == CONSTANT_FIELD ||
+                    tag == CONSTANT_METHOD ||
+                    tag == CONSTANT_INTERFACEMETHOD ||
+                    tag == CONSTANT_NAMEANDTYPE)
+                {
+                    out.writeShort(index1);
+                }
+            }
+
+            public int hashCode() {
+                return tag + index0 + index1;
+            }
+
+            public boolean equals(Object obj) {
+                if (obj instanceof IndirectEntry) {
+                    IndirectEntry other = (IndirectEntry) obj;
+                    if (tag == other.tag &&
+                        index0 == other.index0 && index1 == other.index1)
+                    {
+                        return true;
+                    }
+                }
+                return false;
+            }
+        }
+    }
+}
--- a/src/java.base/share/classes/java/math/BigInteger.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/math/BigInteger.java	Tue Dec 22 09:14:16 2015 -0800
@@ -38,8 +38,8 @@
 import java.util.Random;
 import java.util.concurrent.ThreadLocalRandom;
 
-import sun.misc.DoubleConsts;
-import sun.misc.FloatConsts;
+import jdk.internal.math.DoubleConsts;
+import jdk.internal.math.FloatConsts;
 import jdk.internal.HotSpotIntrinsicCandidate;
 
 /**
--- a/src/java.base/share/classes/java/net/URI.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/net/URI.java	Tue Dec 22 09:14:16 2015 -0800
@@ -33,7 +33,6 @@
 import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
 import java.nio.charset.CharsetDecoder;
-import java.nio.charset.CharsetEncoder;
 import java.nio.charset.CoderResult;
 import java.nio.charset.CodingErrorAction;
 import java.nio.charset.CharacterCodingException;
@@ -495,12 +494,12 @@
     private transient volatile String schemeSpecificPart;
     private transient volatile int hash;        // Zero ==> undefined
 
-    private transient volatile String decodedUserInfo = null;
-    private transient volatile String decodedAuthority = null;
-    private transient volatile String decodedPath = null;
-    private transient volatile String decodedQuery = null;
-    private transient volatile String decodedFragment = null;
-    private transient volatile String decodedSchemeSpecificPart = null;
+    private transient volatile String decodedUserInfo;
+    private transient volatile String decodedAuthority;
+    private transient volatile String decodedPath;
+    private transient volatile String decodedQuery;
+    private transient volatile String decodedFragment;
+    private transient volatile String decodedSchemeSpecificPart;
 
     /**
      * The string form of this URI.
--- a/src/java.base/share/classes/java/net/URL.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/net/URL.java	Tue Dec 22 09:14:16 2015 -0800
@@ -310,7 +310,8 @@
      * @param      host       the name of the host.
      * @param      port       the port number on the host.
      * @param      file       the file on the host
-     * @exception  MalformedURLException  if an unknown protocol is specified.
+     * @exception  MalformedURLException  if an unknown protocol or the port
+     *                  is a negative number other than -1
      * @see        java.lang.System#getProperty(java.lang.String)
      * @see        java.net.URL#setURLStreamHandlerFactory(
      *                  java.net.URLStreamHandlerFactory)
@@ -329,9 +330,9 @@
      * name, {@code host} name, and {@code file} name. The
      * default port for the specified protocol is used.
      * <p>
-     * This method is equivalent to calling the four-argument
-     * constructor with the arguments being {@code protocol},
-     * {@code host}, {@code -1}, and {@code file}.
+     * This constructor is equivalent to the four-argument
+     * constructor with the only difference of using the
+     * default port for the specified protocol.
      *
      * No validation of the inputs is performed by this constructor.
      *
@@ -372,7 +373,8 @@
      * @param      port       the port number on the host.
      * @param      file       the file on the host
      * @param      handler    the stream handler for the URL.
-     * @exception  MalformedURLException  if an unknown protocol is specified.
+     * @exception  MalformedURLException  if an unknown protocol or the port
+                        is a negative number other than -1
      * @exception  SecurityException
      *        if a security manager exists and its
      *        {@code checkPermission} method doesn't allow
@@ -446,7 +448,9 @@
      *
      * @param      spec   the {@code String} to parse as a URL.
      * @exception  MalformedURLException  if no protocol is specified, or an
-     *               unknown protocol is found, or {@code spec} is {@code null}.
+     *               unknown protocol is found, or {@code spec} is {@code null},
+     *               or the parsed URL fails to comply with the specific syntax
+     *               of the associated protocol.
      * @see        java.net.URL#URL(java.net.URL, java.lang.String)
      */
     public URL(String spec) throws MalformedURLException {
@@ -493,7 +497,9 @@
      * @param      context   the context in which to parse the specification.
      * @param      spec      the {@code String} to parse as a URL.
      * @exception  MalformedURLException  if no protocol is specified, or an
-     *               unknown protocol is found, or {@code spec} is {@code null}.
+     *               unknown protocol is found, or {@code spec} is {@code null},
+     *               or the parsed URL fails to comply with the specific syntax
+     *               of the associated protocol.
      * @see        java.net.URL#URL(java.lang.String, java.lang.String,
      *                  int, java.lang.String)
      * @see        java.net.URLStreamHandler
@@ -513,7 +519,9 @@
      * @param      spec      the {@code String} to parse as a URL.
      * @param      handler   the stream handler for the URL.
      * @exception  MalformedURLException  if no protocol is specified, or an
-     *               unknown protocol is found, or {@code spec} is {@code null}.
+     *               unknown protocol is found, or {@code spec} is {@code null},
+     *               or the parsed URL fails to comply with the specific syntax
+     *               of the associated protocol.
      * @exception  SecurityException
      *        if a security manager exists and its
      *        {@code checkPermission} method doesn't allow
--- a/src/java.base/share/classes/java/nio/Bits.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/nio/Bits.java	Tue Dec 22 09:14:16 2015 -0800
@@ -25,9 +25,7 @@
 
 package java.nio;
 
-import java.security.AccessController;
 import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.atomic.LongAdder;
 
 import jdk.internal.misc.JavaNioAccess;
 import jdk.internal.misc.JavaLangRefAccess;
@@ -603,7 +601,8 @@
     private static final AtomicLong reservedMemory = new AtomicLong();
     private static final AtomicLong totalCapacity = new AtomicLong();
     private static final AtomicLong count = new AtomicLong();
-    private static volatile boolean memoryLimitSet = false;
+    private static volatile boolean memoryLimitSet;
+
     // max. number of sleeps during try-reserving with exponentially
     // increasing delay before throwing OutOfMemoryError:
     // 1, 2, 4, 8, 16, 32, 64, 128, 256 (total 511 ms ~ 0.5 s)
--- a/src/java.base/share/classes/java/nio/channels/SelectionKey.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/nio/channels/SelectionKey.java	Tue Dec 22 09:14:16 2015 -0800
@@ -26,8 +26,6 @@
 package java.nio.channels;
 
 import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
-import java.io.IOException;
-
 
 /**
  * A token representing the registration of a {@link SelectableChannel} with a
@@ -363,7 +361,7 @@
 
     // -- Attachments --
 
-    private volatile Object attachment = null;
+    private volatile Object attachment;
 
     private static final AtomicReferenceFieldUpdater<SelectionKey,Object>
         attachmentUpdater = AtomicReferenceFieldUpdater.newUpdater(
--- a/src/java.base/share/classes/java/nio/channels/spi/AbstractInterruptibleChannel.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/nio/channels/spi/AbstractInterruptibleChannel.java	Tue Dec 22 09:14:16 2015 -0800
@@ -29,11 +29,7 @@
 package java.nio.channels.spi;
 
 import java.io.IOException;
-import java.lang.reflect.Method;
-import java.lang.reflect.InvocationTargetException;
 import java.nio.channels.*;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
 import jdk.internal.misc.SharedSecrets;
 import sun.nio.ch.Interruptible;
 
@@ -90,7 +86,7 @@
 {
 
     private final Object closeLock = new Object();
-    private volatile boolean open = true;
+    private volatile boolean closed;
 
     /**
      * Initializes a new instance of this class.
@@ -110,9 +106,9 @@
      */
     public final void close() throws IOException {
         synchronized (closeLock) {
-            if (!open)
+            if (closed)
                 return;
-            open = false;
+            closed = true;
             implCloseChannel();
         }
     }
@@ -136,7 +132,7 @@
     protected abstract void implCloseChannel() throws IOException;
 
     public final boolean isOpen() {
-        return open;
+        return !closed;
     }
 
 
@@ -158,9 +154,9 @@
             interruptor = new Interruptible() {
                     public void interrupt(Thread target) {
                         synchronized (closeLock) {
-                            if (!open)
+                            if (closed)
                                 return;
-                            open = false;
+                            closed = true;
                             interrupted = target;
                             try {
                                 AbstractInterruptibleChannel.this.implCloseChannel();
@@ -202,7 +198,7 @@
             this.interrupted = null;
             throw new ClosedByInterruptException();
         }
-        if (!completed && !open)
+        if (!completed && closed)
             throw new AsynchronousCloseException();
     }
 
--- a/src/java.base/share/classes/java/nio/charset/Charset.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/nio/charset/Charset.java	Tue Dec 22 09:14:16 2015 -0800
@@ -276,7 +276,7 @@
 
     /* -- Static methods -- */
 
-    private static volatile String bugLevel = null;
+    private static volatile String bugLevel;
 
     static boolean atBugLevel(String bl) {              // package-private
         String level = bugLevel;
@@ -324,8 +324,8 @@
     // Cache of the most-recently-returned charsets,
     // along with the names that were used to find them
     //
-    private static volatile Object[] cache1 = null; // "Level 1" cache
-    private static volatile Object[] cache2 = null; // "Level 2" cache
+    private static volatile Object[] cache1; // "Level 1" cache
+    private static volatile Object[] cache2; // "Level 2" cache
 
     private static void cache(String charsetName, Charset cs) {
         cache2 = cache1;
--- a/src/java.base/share/classes/java/security/SecureRandom.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/security/SecureRandom.java	Tue Dec 22 09:14:16 2015 -0800
@@ -124,7 +124,7 @@
     private String algorithm;
 
     // Seed Generator
-    private static volatile SecureRandom seedGenerator = null;
+    private static volatile SecureRandom seedGenerator;
 
     /**
      * Constructs a secure random number generator (RNG) implementing the
@@ -522,10 +522,12 @@
      * @see #setSeed
      */
     public static byte[] getSeed(int numBytes) {
-        if (seedGenerator == null) {
-            seedGenerator = new SecureRandom();
+        SecureRandom seedGen = seedGenerator;
+        if (seedGen == null) {
+            seedGen = new SecureRandom();
+            seedGenerator = seedGen;
         }
-        return seedGenerator.generateSeed(numBytes);
+        return seedGen.generateSeed(numBytes);
     }
 
     /**
--- a/src/java.base/share/classes/java/text/DateFormatSymbols.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/text/DateFormatSymbols.java	Tue Dec 22 09:14:16 2015 -0800
@@ -630,7 +630,9 @@
             hashCode = 11 * hashCode + Arrays.hashCode(ampms);
             hashCode = 11 * hashCode + Arrays.deepHashCode(getZoneStringsWrapper());
             hashCode = 11 * hashCode + Objects.hashCode(localPatternChars);
-            cachedHashCode = hashCode;
+            if (hashCode != 0) {
+                cachedHashCode = hashCode;
+            }
         }
 
         return hashCode;
@@ -670,12 +672,12 @@
     private static final ConcurrentMap<Locale, SoftReference<DateFormatSymbols>> cachedInstances
         = new ConcurrentHashMap<>(3);
 
-    private transient int lastZoneIndex = 0;
+    private transient int lastZoneIndex;
 
     /**
      * Cached hash code
      */
-    transient volatile int cachedHashCode = 0;
+    transient volatile int cachedHashCode;
 
     private void initializeData(Locale desiredLocale) {
         locale = desiredLocale;
--- a/src/java.base/share/classes/java/text/DecimalFormatSymbols.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/text/DecimalFormatSymbols.java	Tue Dec 22 09:14:16 2015 -0800
@@ -42,14 +42,8 @@
 import java.io.ObjectInputStream;
 import java.io.Serializable;
 import java.text.spi.DecimalFormatSymbolsProvider;
-import java.util.ArrayList;
 import java.util.Currency;
-import java.util.List;
 import java.util.Locale;
-import java.util.MissingResourceException;
-import java.util.ResourceBundle;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
 import sun.util.locale.provider.LocaleProviderAdapter;
 import sun.util.locale.provider.LocaleServiceProviderPool;
 import sun.util.locale.provider.ResourceBundleBasedAdapter;
@@ -875,7 +869,7 @@
 
     // currency; only the ISO code is serialized.
     private transient Currency currency;
-    private transient volatile boolean currencyInitialized = false;
+    private transient volatile boolean currencyInitialized;
 
     // Proclaim JDK 1.1 FCS compatibility
     static final long serialVersionUID = 5772796243397350300L;
--- a/src/java.base/share/classes/java/text/DigitList.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/text/DigitList.java	Tue Dec 22 09:14:16 2015 -0800
@@ -41,7 +41,7 @@
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.math.RoundingMode;
-import sun.misc.FloatingDecimal;
+import jdk.internal.math.FloatingDecimal;
 
 /**
  * Digit List. Private to DecimalFormat.
--- a/src/java.base/share/classes/java/text/SimpleDateFormat.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/text/SimpleDateFormat.java	Tue Dec 22 09:14:16 2015 -0800
@@ -1856,6 +1856,7 @@
             if (patternCharIndex == PATTERN_HOUR_OF_DAY1 ||
                 patternCharIndex == PATTERN_HOUR1 ||
                 (patternCharIndex == PATTERN_MONTH && count <= 2) ||
+                (patternCharIndex == PATTERN_MONTH_STANDALONE && count <= 2) ||
                 patternCharIndex == PATTERN_YEAR ||
                 patternCharIndex == PATTERN_WEEK_YEAR) {
                 // It would be good to unify this with the obeyCount logic below,
@@ -1976,6 +1977,20 @@
                 }
                 break parsing;
 
+            case PATTERN_MONTH_STANDALONE: // 'L'
+                if (count <= 2) {
+                    // Don't want to parse the month if it is a string
+                    // while pattern uses numeric style: L or LL
+                    //[we computed 'value' above.]
+                    calb.set(Calendar.MONTH, value - 1);
+                    return pos.index;
+                }
+                Map<String, Integer> maps = getDisplayNamesMap(field, locale);
+                if ((index = matchString(text, start, field, maps, calb)) > 0) {
+                    return index;
+                }
+                break parsing;
+
             case PATTERN_HOUR_OF_DAY1: // 'k' 1-based.  eg, 23:59 + 1 hour =>> 24:59
                 if (!isLenient()) {
                     // Validate the hour value in non-lenient
--- a/src/java.base/share/classes/java/time/Duration.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/time/Duration.java	Tue Dec 22 09:14:16 2015 -0800
@@ -997,6 +997,24 @@
      }
 
     /**
+     * Returns number of whole times a specified Duration occurs within this Duration.
+     * <p>
+     * This instance is immutable and unaffected by this method call.
+     *
+     * @param divisor the value to divide the duration by, positive or negative, not null
+     * @return number of whole times, rounded toward zero, a specified
+     *         {@code Duration} occurs within this Duration, may be negative
+     * @throws ArithmeticException if the divisor is zero, or if numeric overflow occurs
+     * @since 9
+     */
+    public long dividedBy(Duration divisor) {
+        Objects.requireNonNull(divisor, "divisor");
+        BigDecimal dividendBigD = toBigDecimalSeconds();
+        BigDecimal divisorBigD = divisor.toBigDecimalSeconds();
+        return dividendBigD.divideToIntegralValue(divisorBigD).longValueExact();
+    }
+
+    /**
      * Converts this duration to the total length in seconds and
      * fractional nanoseconds expressed as a {@code BigDecimal}.
      *
--- a/src/java.base/share/classes/java/util/AbstractMap.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/util/AbstractMap.java	Tue Dec 22 09:14:16 2015 -0800
@@ -304,9 +304,28 @@
      * Each of these fields are initialized to contain an instance of the
      * appropriate view the first time this view is requested.  The views are
      * stateless, so there's no reason to create more than one of each.
+     *
+     * <p>Since there is no synchronization performed while accessing these fields,
+     * it is expected that java.util.Map view classes using these fields have
+     * no non-final fields (or any fields at all except for outer-this). Adhering
+     * to this rule would make the races on these fields benign.
+     *
+     * <p>It is also imperative that implementations read the field only once,
+     * as in:
+     *
+     * <pre> {@code
+     * public Set<K> keySet() {
+     *   Set<K> ks = keySet;  // single racy read
+     *   if (ks == null) {
+     *     ks = new KeySet();
+     *     keySet = ks;
+     *   }
+     *   return ks;
+     * }
+     *}</pre>
      */
-    transient volatile Set<K>        keySet;
-    transient volatile Collection<V> values;
+    transient Set<K>        keySet;
+    transient Collection<V> values;
 
     /**
      * {@inheritDoc}
@@ -325,8 +344,9 @@
      * method will not all return the same set.
      */
     public Set<K> keySet() {
-        if (keySet == null) {
-            keySet = new AbstractSet<K>() {
+        Set<K> ks = keySet;
+        if (ks == null) {
+            ks = new AbstractSet<K>() {
                 public Iterator<K> iterator() {
                     return new Iterator<K>() {
                         private Iterator<Entry<K,V>> i = entrySet().iterator();
@@ -361,8 +381,9 @@
                     return AbstractMap.this.containsKey(k);
                 }
             };
+            keySet = ks;
         }
-        return keySet;
+        return ks;
     }
 
     /**
@@ -382,8 +403,9 @@
      * method will not all return the same collection.
      */
     public Collection<V> values() {
-        if (values == null) {
-            values = new AbstractCollection<V>() {
+        Collection<V> vals = values;
+        if (vals == null) {
+            vals = new AbstractCollection<V>() {
                 public Iterator<V> iterator() {
                     return new Iterator<V>() {
                         private Iterator<Entry<K,V>> i = entrySet().iterator();
@@ -418,8 +440,9 @@
                     return AbstractMap.this.containsValue(v);
                 }
             };
+            values = vals;
         }
-        return values;
+        return vals;
     }
 
     public abstract Set<Entry<K,V>> entrySet();
--- a/src/java.base/share/classes/java/util/Collections.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/util/Collections.java	Tue Dec 22 09:14:16 2015 -0800
@@ -5530,7 +5530,7 @@
      * @since  1.6
      */
     public static <T> Queue<T> asLifoQueue(Deque<T> deque) {
-        return new AsLIFOQueue<>(deque);
+        return new AsLIFOQueue<>(Objects.requireNonNull(deque));
     }
 
     /**
--- a/src/java.base/share/classes/java/util/EnumMap.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/util/EnumMap.java	Tue Dec 22 09:14:16 2015 -0800
@@ -380,10 +380,11 @@
      */
     public Set<K> keySet() {
         Set<K> ks = keySet;
-        if (ks != null)
-            return ks;
-        else
-            return keySet = new KeySet();
+        if (ks == null) {
+            ks = new KeySet();
+            keySet = ks;
+        }
+        return ks;
     }
 
     private class KeySet extends AbstractSet<K> {
@@ -418,10 +419,11 @@
      */
     public Collection<V> values() {
         Collection<V> vs = values;
-        if (vs != null)
-            return vs;
-        else
-            return values = new Values();
+        if (vs == null) {
+            vs = new Values();
+            values = vs;
+        }
+        return vs;
     }
 
     private class Values extends AbstractCollection<V> {
--- a/src/java.base/share/classes/java/util/Formatter.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/util/Formatter.java	Tue Dec 22 09:14:16 2015 -0800
@@ -60,8 +60,8 @@
 import java.time.temporal.TemporalQueries;
 import java.time.temporal.UnsupportedTemporalTypeException;
 
-import sun.misc.DoubleConsts;
-import sun.misc.FormattedFloatingDecimal;
+import jdk.internal.math.DoubleConsts;
+import jdk.internal.math.FormattedFloatingDecimal;
 
 /**
  * An interpreter for printf-style format strings.  This class provides support
--- a/src/java.base/share/classes/java/util/HashMap.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/util/HashMap.java	Tue Dec 22 09:14:16 2015 -0800
@@ -902,8 +902,12 @@
      * @return a set view of the keys contained in this map
      */
     public Set<K> keySet() {
-        Set<K> ks;
-        return (ks = keySet) == null ? (keySet = new KeySet()) : ks;
+        Set<K> ks = keySet;
+        if (ks == null) {
+            ks = new KeySet();
+            keySet = ks;
+        }
+        return ks;
     }
 
     final class KeySet extends AbstractSet<K> {
@@ -949,8 +953,12 @@
      * @return a view of the values contained in this map
      */
     public Collection<V> values() {
-        Collection<V> vs;
-        return (vs = values) == null ? (values = new Values()) : vs;
+        Collection<V> vs = values;
+        if (vs == null) {
+            vs = new Values();
+            values = vs;
+        }
+        return vs;
     }
 
     final class Values extends AbstractCollection<V> {
--- a/src/java.base/share/classes/java/util/IdentityHashMap.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/util/IdentityHashMap.java	Tue Dec 22 09:14:16 2015 -0800
@@ -964,10 +964,11 @@
      */
     public Set<K> keySet() {
         Set<K> ks = keySet;
-        if (ks != null)
-            return ks;
-        else
-            return keySet = new KeySet();
+        if (ks == null) {
+            ks = new KeySet();
+            keySet = ks;
+        }
+        return ks;
     }
 
     private class KeySet extends AbstractSet<K> {
@@ -1069,10 +1070,11 @@
      */
     public Collection<V> values() {
         Collection<V> vs = values;
-        if (vs != null)
-            return vs;
-        else
-            return values = new Values();
+        if (vs == null) {
+            vs = new Values();
+            values = vs;
+        }
+        return vs;
     }
 
     private class Values extends AbstractCollection<V> {
--- a/src/java.base/share/classes/java/util/LinkedHashMap.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/util/LinkedHashMap.java	Tue Dec 22 09:14:16 2015 -0800
@@ -528,8 +528,12 @@
      * @return a set view of the keys contained in this map
      */
     public Set<K> keySet() {
-        Set<K> ks;
-        return (ks = keySet) == null ? (keySet = new LinkedKeySet()) : ks;
+        Set<K> ks = keySet;
+        if (ks == null) {
+            ks = new LinkedKeySet();
+            keySet = ks;
+        }
+        return ks;
     }
 
     final class LinkedKeySet extends AbstractSet<K> {
@@ -577,8 +581,12 @@
      * @return a view of the values contained in this map
      */
     public Collection<V> values() {
-        Collection<V> vs;
-        return (vs = values) == null ? (values = new LinkedValues()) : vs;
+        Collection<V> vs = values;
+        if (vs == null) {
+            vs = new LinkedValues();
+            values = vs;
+        }
+        return vs;
     }
 
     final class LinkedValues extends AbstractCollection<V> {
--- a/src/java.base/share/classes/java/util/Locale.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/util/Locale.java	Tue Dec 22 09:14:16 2015 -0800
@@ -62,7 +62,6 @@
 import sun.util.locale.provider.LocaleProviderAdapter;
 import sun.util.locale.provider.LocaleResources;
 import sun.util.locale.provider.LocaleServiceProviderPool;
-import sun.util.locale.provider.ResourceBundleBasedAdapter;
 
 /**
  * A <code>Locale</code> object represents a specific geographical, political,
@@ -2016,11 +2015,11 @@
     /**
      * Calculated hashcode
      */
-    private transient volatile int hashCodeValue = 0;
+    private transient volatile int hashCodeValue;
 
     private static volatile Locale defaultLocale = initDefault();
-    private static volatile Locale defaultDisplayLocale = null;
-    private static volatile Locale defaultFormatLocale = null;
+    private static volatile Locale defaultDisplayLocale;
+    private static volatile Locale defaultFormatLocale;
 
     private transient volatile String languageTag;
 
@@ -2207,9 +2206,9 @@
                 baseLocale.getRegion(), baseLocale.getVariant(), localeExtensions);
     }
 
-    private static volatile String[] isoLanguages = null;
+    private static volatile String[] isoLanguages;
 
-    private static volatile String[] isoCountries = null;
+    private static volatile String[] isoCountries;
 
     private static String convertOldISOCodes(String language) {
         // we accept both the old and the new ISO codes for the languages whose ISO
@@ -2851,7 +2850,7 @@
         private final String range;
         private final double weight;
 
-        private volatile int hash = 0;
+        private volatile int hash;
 
         /**
          * Constructs a {@code LanguageRange} using the given {@code range}.
@@ -3108,14 +3107,17 @@
          */
         @Override
         public int hashCode() {
-            if (hash == 0) {
-                int result = 17;
-                result = 37*result + range.hashCode();
+            int h = hash;
+            if (h == 0) {
+                h = 17;
+                h = 37*h + range.hashCode();
                 long bitsWeight = Double.doubleToLongBits(weight);
-                result = 37*result + (int)(bitsWeight ^ (bitsWeight >>> 32));
-                hash = result;
+                h = 37*h + (int)(bitsWeight ^ (bitsWeight >>> 32));
+                if (h != 0) {
+                    hash = h;
+                }
             }
-            return hash;
+            return h;
         }
 
         /**
--- a/src/java.base/share/classes/java/util/TreeMap.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/util/TreeMap.java	Tue Dec 22 09:14:16 2015 -0800
@@ -852,7 +852,11 @@
      */
     public Collection<V> values() {
         Collection<V> vs = values;
-        return (vs != null) ? vs : (values = new Values());
+        if (vs == null) {
+            vs = new Values();
+            values = vs;
+        }
+        return vs;
     }
 
     /**
--- a/src/java.base/share/classes/java/util/WeakHashMap.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/util/WeakHashMap.java	Tue Dec 22 09:14:16 2015 -0800
@@ -866,7 +866,11 @@
      */
     public Set<K> keySet() {
         Set<K> ks = keySet;
-        return (ks != null ? ks : (keySet = new KeySet()));
+        if (ks == null) {
+            ks = new KeySet();
+            keySet = ks;
+        }
+        return ks;
     }
 
     private class KeySet extends AbstractSet<K> {
@@ -915,7 +919,11 @@
      */
     public Collection<V> values() {
         Collection<V> vs = values;
-        return (vs != null) ? vs : (values = new Values());
+        if (vs == null) {
+            vs = new Values();
+            values = vs;
+        }
+        return vs;
     }
 
     private class Values extends AbstractCollection<V> {
--- a/src/java.base/share/classes/java/util/regex/Pattern.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/util/regex/Pattern.java	Tue Dec 22 09:14:16 2015 -0800
@@ -950,7 +950,7 @@
      * Boolean indicating this Pattern is compiled; this is necessary in order
      * to lazily compile deserialized Patterns.
      */
-    private transient volatile boolean compiled = false;
+    private transient volatile boolean compiled;
 
     /**
      * The normalized pattern string.
@@ -1332,7 +1332,6 @@
         localCount = 0;
 
         // if length > 0, the Pattern is lazily compiled
-        compiled = false;
         if (pattern.length() == 0) {
             root = new Start(lastAccept);
             matchRoot = lastAccept;
@@ -1377,7 +1376,6 @@
      * equivalences of the characters.
      */
     private void normalize() {
-        boolean inCharClass = false;
         int lastCodePoint = -1;
 
         // Convert pattern into normalized form
@@ -1551,7 +1549,6 @@
         // offset maintains the index in code units.
 loop:   for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
             len = countChars(input, offset, 1);
-            boolean skip = false;
             for(int y=x-1; y>=0; y--) {
                 if (combClass[y] == combClass[x]) {
                     continue loop;
@@ -1566,8 +1563,7 @@
                 temp[index++] = prefix + sre;
         }
         String[] result = new String[index];
-        for (int x=0; x<index; x++)
-            result[x] = temp[x];
+        System.arraycopy(temp, 0, result, 0, index);
         return result;
     }
 
@@ -1742,9 +1738,11 @@
     }
 
     Map<String, Integer> namedGroups() {
-        if (namedGroups == null)
-            namedGroups = new HashMap<>(2);
-        return namedGroups;
+        Map<String, Integer> groups = namedGroups;
+        if (groups == null) {
+            namedGroups = groups = new HashMap<>(2);
+        }
+        return groups;
     }
 
     /**
--- a/src/java.base/share/classes/java/util/zip/ZipFile.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/java/util/zip/ZipFile.java	Tue Dec 22 09:14:16 2015 -0800
@@ -72,7 +72,7 @@
 class ZipFile implements ZipConstants, Closeable {
 
     private final String name;     // zip file name
-    private volatile boolean closeRequested = false;
+    private volatile boolean closeRequested;
     private Source zsrc;
     private ZipCoder zc;
 
@@ -366,7 +366,7 @@
     }
 
     private class ZipFileInflaterInputStream extends InflaterInputStream {
-        private volatile boolean closeRequested = false;
+        private volatile boolean closeRequested;
         private boolean eof = false;
         private final ZipFileInputStream zfin;
 
@@ -653,7 +653,7 @@
      * (possibly compressed) zip file entry.
      */
    private class ZipFileInputStream extends InputStream {
-        private volatile boolean closeRequested = false;
+        private volatile boolean closeRequested;
         private   long pos;     // current position within entry data
         protected long rem;     // number of remaining bytes within entry
         protected long size;    // uncompressed size of this entry
@@ -833,7 +833,8 @@
             byte[] cen = zsrc.cen;
             for (int i = 0; i < names.length; i++) {
                 int pos = zsrc.metanames.get(i);
-                names[i] = zc.toStringUTF8(cen, pos + CENHDR,  CENNAM(cen, pos));
+                names[i] = new String(cen, pos + CENHDR,  CENNAM(cen, pos),
+                                      StandardCharsets.UTF_8);
             }
             return names;
         }
--- a/src/java.base/share/classes/jdk/internal/logger/LazyLoggers.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/jdk/internal/logger/LazyLoggers.java	Tue Dec 22 09:14:16 2015 -0800
@@ -326,20 +326,22 @@
     }
 
     // Do not expose this outside of this package.
-    private static volatile LoggerFinder provider = null;
+    private static volatile LoggerFinder provider;
     private static LoggerFinder accessLoggerFinder() {
-        if (provider == null) {
+        LoggerFinder prov = provider;
+        if (prov == null) {
             // no need to lock: it doesn't matter if we call
             // getLoggerFinder() twice - since LoggerFinder already caches
             // the result.
             // This is just an optimization to avoid the cost of calling
             // doPrivileged every time.
             final SecurityManager sm = System.getSecurityManager();
-            provider = sm == null ? LoggerFinder.getLoggerFinder() :
+            prov = sm == null ? LoggerFinder.getLoggerFinder() :
                 AccessController.doPrivileged(
                         (PrivilegedAction<LoggerFinder>)LoggerFinder::getLoggerFinder);
+            provider = prov;
         }
-        return provider;
+        return prov;
     }
 
     // Avoid using lambda here as lazy loggers could be created early
--- a/src/java.base/share/classes/jdk/internal/logger/SimpleConsoleLogger.java	Mon Dec 14 14:12:17 2015 -0800
+++ b/src/java.base/share/classes/jdk/internal/logger/SimpleConsoleLogger.java	Tue Dec 22 09:14:16 2015 -0800
@@ -28,6 +28,7 @@
 import java.io.PrintStream;
 import java.io.PrintWriter;
 import java.io.StringWriter;
+import java.lang.StackWalker.StackFrame;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.time.ZonedDateTime;
@@ -180,7 +181,16 @@
      * CallerFinder is a stateful predicate.
      */
     static final class CallerFinder implements Predicate<StackWalker.StackFrame> {
-        static final StackWalker WALKER = StackWalker.getInstance();
+        private static final StackWalker WALKER;
+        static {
+            final PrivilegedAction<StackWalker> action = new PrivilegedAction<>() {
+                @Override
+                public StackWalker run() {
+                    return StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
+                }
+            };
+            WALKER = AccessController.doPrivileged(action);
+        }
 
         /**
          * Returns StackFrame of the caller's frame.
@@ -210,8 +220,9 @@
                 lookingForLogger = !isLoggerImplFrame(cname);
                 return false;
             }
-            // We've found the relevant frame.
-            return !skipLoggingFrame(cname) && !isLoggerImplFrame(cname);
+            // Continue walking until we've found the relevant calling frame.
+            // Skips logging/logger infrastructure.
+            return !isFilteredFrame(t);
         }
 
         private boolean isLoggerImplFrame(String cname) {
@@ -281,8 +292,8 @@
         return Formatting.getSimpleFormat(defaultPropertyGetter);
     }
 
-    public static boolean skipLoggingFrame(String cname) {
-        return Formatting.skipLoggingFrame(cname);
+    public static boolean isFilteredFrame(StackFrame st) {
+        return Formatting.isFilteredFrame(st);
     }
 
     @Override
@@ -393,16 +404,19 @@
 
         }
 
-        static boolean skipLoggingFrame(String cname) {
+        static boolean isFilteredFrame(StackFrame st) {
             // skip logging/logger infrastructure
+            if (System.Logger.class.isAssignableFrom(st.getDeclaringClass())) {
+                return true;
+            }
 
             // fast escape path: all the prefixes below start with 's' or 'j' and
             // have more than 12 characters.
+            final String cname = st.getClassName();
             char c = cname.length() < 12 ? 0 : cname.charAt(0);
             if (c == 's') {
                 // skip internal machinery classes
                 if (cname.startsWith("sun.util.logging."))   return true;
-                if (cname.startsWith("sun.reflect."))        return true;
                 if (cname.startsWith("sun.rmi.runtime.Log")) return true;
             } else if (c == 'j') {
                 // Message delayed at Bootstrap: no need to go further up.
@@ -410,10 +424,7 @@
                 // skip public machinery classes
                 if (cname.startsWith("jdk.internal.logger."))          return true;
                 if (cname.startsWith("java.util.logging."))            return true;
-                if (cname.startsWith("java.lang.System$Logger"))       return true;
-                if (cname.startsWith("java.lang.reflect."))            return true;
                 if (cname.startsWith("java.lang.invoke.MethodHandle")) return true;
-                if (cname.startsWith("java.lang.invoke.LambdaForm"))    return true;
                 if (cname.startsWith("java.security.AccessController")) return true;
             }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/math/DoubleConsts.java	Tue Dec 22 09:14:16 2015 -0800
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.math;
+
+/**
+ * This class contains additional constants documenting limits of the
+ * <code>double</code> type.
+ *
+ * @author Joseph D. Darcy
+ */
+
+public class DoubleConsts {
+    /**
+     * Don't let anyone instantiate this class.
+     */
+    private DoubleConsts() {}
+
+    public static final double POSITIVE_INFINITY = java.lang.Double.POSITIVE_INFINITY;
+    public static final double NEGATIVE_INFINITY = java.lang.Double.NEGATIVE_INFINITY;
+    public static final double NaN = java.lang.Double.NaN;
+    public static final double MAX_VALUE = java.lang.Double.MAX_VALUE;
+    public static final double MIN_VALUE = java.lang.Double.MIN_VALUE;
+
+    /**
+     * A constant holding the smallest positive normal value of type
+     * <code>double</code>, 2<sup>-1022</sup>.  It is equal to the
+     * value returned by
+     * <code>Double.longBitsToDouble(0x0010000000000000L)</code>.
+     *
+     * @since 1.5
+     */
+    public static final double  MIN_NORMAL      = 2.2250738585072014E-308;
+
+
+    /**
+     * The number of logical bits in the significand of a
+     * <code>double</code> number, including the implicit bit.
+     */
+    public static final int SIGNIFICAND_WIDTH   = 53;
+
+    /**
+     * Maximum exponent a finite <code>double</code> number may have.
+     * It is equal to the value returned by
+     * <code>Math.ilogb(Double.MAX_VALUE)</code>.
+     */
+    public static final int     MAX_EXPONENT    = 1023;
+
+    /**
+     * Minimum exponent a normalized <code>double</code> number may
+     * have.  It is equal to the value returned by
+     * <code>Math.ilogb(Double.MIN_NORMAL)</code>.
+     */
+    public static final int     MIN_EXPONENT    = -1022;
+
+    /**
+     * The exponent the smallest positive <code>double</code>
+     * subnormal value would have if it could be normalized..
+     */
+    public static final int     MIN_SUB_EXPONENT = MIN_EXPONENT -
+                                                   (SIGNIFICAND_WIDTH - 1);
+
+    /**
+     * Bias used in representing a <code>double</code> exponent.
+     */
+    public static final int     EXP_BIAS        = 1023;
+
+    /**
+     * Bit mask to isolate the sign bit of a <code>double</code>.
+     */
+    public static final long    SIGN_BIT_MASK   = 0x8000000000000000L;
+
+    /**
+     * Bit mask to isolate the exponent field of a
+     * <code>double</code>.
+     */
+    public static final long    EXP_BIT_MASK    = 0x7FF0000000000000L;
+
+    /**
+     * Bit mask to isolate the significand field of a
+     * <code>double</code>.
+     */
+    public static final long    SIGNIF_BIT_MASK = 0x000FFFFFFFFFFFFFL;
+
+    static {
+        // verify bit masks cover all bit positions and that the bit
+        // masks are non-overlapping
+        assert(((SIGN_BIT_MASK | EXP_BIT_MASK | SIGNIF_BIT_MASK) == ~0L) &&
+               (((SIGN_BIT_MASK & EXP_BIT_MASK) == 0L) &&
+                ((SIGN_BIT_MASK & SIGNIF_BIT_MASK) == 0L) &&
+                ((EXP_BIT_MASK & SIGNIF_BIT_MASK) == 0L)));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/math/FDBigInteger.java	Tue Dec 22 09:14:16 2015 -0800
@@ -0,0 +1,1508 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.math;
+
+import java.math.BigInteger;
+import java.util.Arrays;
+//@ model import org.jmlspecs.models.JMLMath;
+
+/**
+ * A simple big integer package specifically for floating point base conversion.
+ */
+public /*@ spec_bigint_math @*/ class FDBigInteger {
+
+    //
+    // This class contains many comments that start with "/*@" mark.
+    // They are behavourial specification in
+    // the Java Modelling Language (JML):
+    // http://www.eecs.ucf.edu/~leavens/JML//index.shtml
+    //
+
+    /*@
+    @ public pure model static \bigint UNSIGNED(int v) {
+    @     return v >= 0 ? v : v + (((\bigint)1) << 32);
+    @ }
+    @
+    @ public pure model static \bigint UNSIGNED(long v) {
+    @     return v >= 0 ? v : v + (((\bigint)1) << 64);
+    @ }
+    @
+    @ public pure model static \bigint AP(int[] data, int len) {
+    @     return (\sum int i; 0 <= 0 && i < len; UNSIGNED(data[i]) << (i*32));
+    @ }
+    @
+    @ public pure model static \bigint pow52(int p5, int p2) {
+    @     ghost \bigint v = 1;
+    @     for (int i = 0; i < p5; i++) v *= 5;
+    @     return v << p2;
+    @ }
+    @
+    @ public pure model static \bigint pow10(int p10) {
+    @     return pow52(p10, p10);
+    @ }
+    @*/
+
+    static final int[] SMALL_5_POW = {
+            1,
+            5,
+            5 * 5,
+            5 * 5 * 5,
+            5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5
+    };
+
+    static final long[] LONG_5_POW = {
+            1L,
+            5L,
+            5L * 5,
+            5L * 5 * 5,
+            5L * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+    };
+
+    // Maximum size of cache of powers of 5 as FDBigIntegers.
+    private static final int MAX_FIVE_POW = 340;
+
+    // Cache of big powers of 5 as FDBigIntegers.
+    private static final FDBigInteger POW_5_CACHE[];
+
+    // Initialize FDBigInteger cache of powers of 5.
+    static {
+        POW_5_CACHE = new FDBigInteger[MAX_FIVE_POW];
+        int i = 0;
+        while (i < SMALL_5_POW.length) {
+            FDBigInteger pow5 = new FDBigInteger(new int[]{SMALL_5_POW[i]}, 0);
+            pow5.makeImmutable();
+            POW_5_CACHE[i] = pow5;
+            i++;
+        }
+        FDBigInteger prev = POW_5_CACHE[i - 1];
+        while (i < MAX_FIVE_POW) {
+            POW_5_CACHE[i] = prev = prev.mult(5);
+            prev.makeImmutable();
+            i++;
+        }
+    }
+
+    // Zero as an FDBigInteger.
+    public static final FDBigInteger ZERO = new FDBigInteger(new int[0], 0);
+
+    // Ensure ZERO is immutable.
+    static {
+        ZERO.makeImmutable();
+    }
+
+    // Constant for casting an int to a long via bitwise AND.
+    private static final long LONG_MASK = 0xffffffffL;
+
+    //@ spec_public non_null;
+    private int data[];  // value: data[0] is least significant
+    //@ spec_public;
+    private int offset;  // number of least significant zero padding ints
+    //@ spec_public;
+    private int nWords;  // data[nWords-1]!=0, all values above are zero
+                 // if nWords==0 -> this FDBigInteger is zero
+    //@ spec_public;
+    private boolean isImmutable = false;
+
+    /*@
+     @ public invariant 0 <= nWords && nWords <= data.length && offset >= 0;
+     @ public invariant nWords == 0 ==> offset == 0;
+     @ public invariant nWords > 0 ==> data[nWords - 1] != 0;
+     @ public invariant (\forall int i; nWords <= i && i < data.length; data[i] == 0);
+     @ public pure model \bigint value() {
+     @     return AP(data, nWords) << (offset*32);
+     @ }
+     @*/
+
+    /**
+     * Constructs an <code>FDBigInteger</code> from data and padding. The
+     * <code>data</code> parameter has the least significant <code>int</code> at
+     * the zeroth index. The <code>offset</code> parameter gives the number of
+     * zero <code>int</code>s to be inferred below the least significant element
+     * of <code>data</code>.
+     *
+     * @param data An array containing all non-zero <code>int</code>s of the value.
+     * @param offset An offset indicating the number of zero <code>int</code>s to pad
+     * below the least significant element of <code>data</code>.
+     */
+    /*@
+     @ requires data != null && offset >= 0;
+     @ ensures this.value() == \old(AP(data, data.length) << (offset*32));
+     @ ensures this.data == \old(data);
+     @*/
+    private FDBigInteger(int[] data, int offset) {
+        this.data = data;
+        this.offset = offset;
+        this.nWords = data.length;
+        trimLeadingZeros();
+    }
+
+    /**
+     * Constructs an <code>FDBigInteger</code> from a starting value and some
+     * decimal digits.
+     *
+     * @param lValue The starting value.
+     * @param digits The decimal digits.
+     * @param kDigits The initial index into <code>digits</code>.
+     * @param nDigits The final index into <code>digits</code>.
+     */
+    /*@
+     @ requires digits != null;
+     @ requires 0 <= kDigits && kDigits <= nDigits && nDigits <= digits.length;
+     @ requires (\forall int i; 0 <= i && i < nDigits; '0' <= digits[i] && digits[i] <= '9');
+     @ ensures this.value() == \old(lValue * pow10(nDigits - kDigits) + (\sum int i; kDigits <= i && i < nDigits; (digits[i] - '0') * pow10(nDigits - i - 1)));
+     @*/
+    public FDBigInteger(long lValue, char[] digits, int kDigits, int nDigits) {
+        int n = Math.max((nDigits + 8) / 9, 2);        // estimate size needed.
+        data = new int[n];      // allocate enough space
+        data[0] = (int) lValue;    // starting value
+        data[1] = (int) (lValue >>> 32);
+        offset = 0;
+        nWords = 2;
+        int i = kDigits;
+        int limit = nDigits - 5;       // slurp digits 5 at a time.
+        int v;
+        while (i < limit) {
+            int ilim = i + 5;
+            v = (int) digits[i++] - (int) '0';
+            while (i < ilim) {
+                v = 10 * v + (int) digits[i++] - (int) '0';
+            }
+            multAddMe(100000, v); // ... where 100000 is 10^5.
+        }
+        int factor = 1;
+        v = 0;
+        while (i < nDigits) {
+            v = 10 * v + (int) digits[i++] - (int) '0';
+            factor *= 10;
+        }
+        if (factor != 1) {
+            multAddMe(factor, v);
+        }
+        trimLeadingZeros();
+    }
+
+    /**
+     * Returns an <code>FDBigInteger</code> with the numerical value
+     * <code>5<sup>p5</sup> * 2<sup>p2</sup></code>.
+     *
+     * @param p5 The exponent of the power-of-five factor.
+     * @param p2 The exponent of the power-of-two factor.
+     * @return <code>5<sup>p5</sup> * 2<sup>p2</sup></code>
+     */
+    /*@
+     @ requires p5 >= 0 && p2 >= 0;
+     @ assignable \nothing;
+     @ ensures \result.value() == \old(pow52(p5, p2));
+     @*/
+    public static FDBigInteger valueOfPow52(int p5, int p2) {
+        if (p5 != 0) {
+            if (p2 == 0) {
+                return big5pow(p5);
+            } else if (p5 < SMALL_5_POW.length) {
+                int pow5 = SMALL_5_POW[p5];
+                int wordcount = p2 >> 5;
+                int bitcount = p2 & 0x1f;
+                if (bitcount == 0) {
+                    return new FDBigInteger(new int[]{pow5}, wordcount);
+                } else {
+                    return new FDBigInteger(new int[]{
+                            pow5 << bitcount,
+                            pow5 >>> (32 - bitcount)
+                    }, wordcount);
+                }
+            } else {
+                return big5pow(p5).leftShift(p2);
+            }
+        } else {
+            return valueOfPow2(p2);
+        }
+    }
+
+    /**
+     * Returns an <code>FDBigInteger</code> with the numerical value
+     * <code>value * 5<sup>p5</sup> * 2<sup>p2</sup></code>.
+     *
+     * @param value The constant factor.
+     * @param p5 The exponent of the power-of-five factor.
+     * @param p2 The exponent of the power-of-two factor.
+     * @return <code>value * 5<sup>p5</sup> * 2<sup>p2</sup></code>
+     */
+    /*@
+     @ requires p5 >= 0 && p2 >= 0;
+     @ assignable \nothing;
+     @ ensures \result.value() == \old(UNSIGNED(value) * pow52(p5, p2));
+     @*/
+    public static FDBigInteger valueOfMulPow52(long value, int p5, int p2) {
+        assert p5 >= 0 : p5;
+        assert p2 >= 0 : p2;
+        int v0 = (int) value;
+        int v1 = (int) (value >>> 32);
+        int wordcount = p2 >> 5;
+        int bitcount = p2 & 0x1f;
+        if (p5 != 0) {
+            if (p5 < SMALL_5_POW.length) {
+                long pow5 = SMALL_5_POW[p5] & LONG_MASK;
+                long carry = (v0 & LONG_MASK) * pow5;
+                v0 = (int) carry;
+                carry >>>= 32;
+                carry = (v1 & LONG_MASK) * pow5 + carry;
+                v1 = (int) carry;
+                int v2 = (int) (carry >>> 32);
+                if (bitcount == 0) {
+                    return new FDBigInteger(new int[]{v0, v1, v2}, wordcount);
+                } else {
+                    return new FDBigInteger(new int[]{
+                            v0 << bitcount,
+                            (v1 << bitcount) | (v0 >>> (32 - bitcount)),
+                            (v2 << bitcount) | (v1 >>> (32 - bitcount)),
+                            v2 >>> (32 - bitcount)
+                    }, wordcount);
+                }
+            } else {
+                FDBigInteger pow5 = big5pow(p5);
+                int[] r;
+                if (v1 == 0) {
+                    r = new int[pow5.nWords + 1 + ((p2 != 0) ? 1 : 0)];
+                    mult(pow5.data, pow5.nWords, v0, r);
+                } else {
+                    r = new int[pow5.nWords + 2 + ((p2 != 0) ? 1 : 0)];
+                    mult(pow5.data, pow5.nWords, v0, v1, r);
+                }
+                return (new FDBigInteger(r, pow5.offset)).leftShift(p2);
+            }
+        } else if (p2 != 0) {
+            if (bitcount == 0) {
+                return new FDBigInteger(new int[]{v0, v1}, wordcount);
+            } else {
+                return new FDBigInteger(new int[]{
+                         v0 << bitcount,
+                        (v1 << bitcount) | (v0 >>> (32 - bitcount)),
+                        v1 >>> (32 - bitcount)
+                }, wordcount);
+            }
+        }
+        return new FDBigInteger(new int[]{v0, v1}, 0);
+    }
+
+    /**
+     * Returns an <code>FDBigInteger</code> with the numerical value
+     * <code>2<sup>p2</sup></code>.
+     *
+     * @param p2 The exponent of 2.
+     * @return <code>2<sup>p2</sup></code>
+     */
+    /*@
+     @ requires p2 >= 0;
+     @ assignable \nothing;
+     @ ensures \result.value() == pow52(0, p2);
+     @*/
+    private static FDBigInteger valueOfPow2(int p2) {
+        int wordcount = p2 >> 5;
+        int bitcount = p2 & 0x1f;
+        return new FDBigInteger(new int[]{1 << bitcount}, wordcount);
+    }
+
+    /**
+     * Removes all leading zeros from this <code>FDBigInteger</code> adjusting
+     * the offset and number of non-zero leading words accordingly.
+     */
+    /*@
+     @ requires data != null;
+     @ requires 0 <= nWords && nWords <= data.length && offset >= 0;
+     @ requires nWords == 0 ==> offset == 0;
+     @ ensures nWords == 0 ==> offset == 0;
+     @ ensures nWords > 0 ==> data[nWords - 1] != 0;
+     @*/
+    private /*@ helper @*/ void trimLeadingZeros() {
+        int i = nWords;
+        if (i > 0 && (data[--i] == 0)) {
+            //for (; i > 0 && data[i - 1] == 0; i--) ;
+            while(i > 0 && data[i - 1] == 0) {
+                i--;
+            }
+            this.nWords = i;
+            if (i == 0) { // all words are zero
+                this.offset = 0;
+            }
+        }
+    }
+
+    /**
+     * Retrieves the normalization bias of the <code>FDBigIntger</code>. The
+     * normalization bias is a left shift such that after it the highest word
+     * of the value will have the 4 highest bits equal to zero:
+     * {@code (highestWord & 0xf0000000) == 0}, but the next bit should be 1
+     * {@code (highestWord & 0x08000000) != 0}.
+     *
+     * @return The normalization bias.
+     */
+    /*@
+     @ requires this.value() > 0;
+     @*/
+    public /*@ pure @*/ int getNormalizationBias() {
+        if (nWords == 0) {
+            throw new IllegalArgumentException("Zero value cannot be normalized");
+        }
+        int zeros = Integer.numberOfLeadingZeros(data[nWords - 1]);
+        return (zeros < 4) ? 28 + zeros : zeros - 4;
+    }
+
+    // TODO: Why is anticount param needed if it is always 32 - bitcount?
+    /**
+     * Left shifts the contents of one int array into another.
+     *
+     * @param src The source array.
+     * @param idx The initial index of the source array.
+     * @param result The destination array.
+     * @param bitcount The left shift.
+     * @param anticount The left anti-shift, e.g., <code>32-bitcount</code>.
+     * @param prev The prior source value.
+     */
+    /*@
+     @ requires 0 < bitcount && bitcount < 32 && anticount == 32 - bitcount;
+     @ requires src.length >= idx && result.length > idx;
+     @ assignable result[*];
+     @ ensures AP(result, \old(idx + 1)) == \old((AP(src, idx) + UNSIGNED(prev) << (idx*32)) << bitcount);
+     @*/
+    private static void leftShift(int[] src, int idx, int result[], int bitcount, int anticount, int prev){
+        for (; idx > 0; idx--) {
+            int v = (prev << bitcount);
+            prev = src[idx - 1];
+            v |= (prev >>> anticount);
+            result[idx] = v;
+        }
+        int v = prev << bitcount;
+        result[0] = v;
+    }
+
+    /**
+     * Shifts this <code>FDBigInteger</code> to the left. The shift is performed
+     * in-place unless the <code>FDBigInteger</code> is immutable in which case
+     * a new instance of <code>FDBigInteger</code> is returned.
+     *
+     * @param shift The number of bits to shift left.
+     * @return The shifted <code>FDBigInteger</code>.
+     */
+    /*@
+     @ requires this.value() == 0 || shift == 0;
+     @ assignable \nothing;
+     @ ensures \result == this;
+     @
+     @  also
+     @
+     @ requires this.value() > 0 && shift > 0 && this.isImmutable;
+     @ assignable \nothing;
+     @ ensures \result.value() == \old(this.value() << shift);
+     @
+     @  also
+     @
+     @ requires this.value() > 0 && shift > 0 && this.isImmutable;
+     @ assignable \nothing;
+     @ ensures \result == this;
+     @ ensures \result.value() == \old(this.value() << shift);
+     @*/
+    public FDBigInteger leftShift(int shift) {
+        if (shift == 0 || nWords == 0) {
+            return this;
+        }
+        int wordcount = shift >> 5;
+        int bitcount = shift & 0x1f;
+        if (this.isImmutable) {
+            if (bitcount == 0) {
+                return new FDBigInteger(Arrays.copyOf(data, nWords), offset + wordcount);
+            } else {
+                int anticount = 32 - bitcount;
+                int idx = nWords - 1;
+                int prev = data[idx];
+                int hi = prev >>> anticount;
+                int[] result;
+                if (hi != 0) {
+                    result = new int[nWords + 1];
+                    result[nWords] = hi;
+                } else {
+                    result = new int[nWords];
+                }
+                leftShift(data,idx,result,bitcount,anticount,prev);
+                return new FDBigInteger(result, offset + wordcount);
+            }
+        } else {
+            if (bitcount != 0) {
+                int anticount = 32 - bitcount;
+                if ((data[0] << bitcount) == 0) {
+                    int idx = 0;
+                    int prev = data[idx];
+                    for (; idx < nWords - 1; idx++) {
+                        int v = (prev >>> anticount);
+                        prev = data[idx + 1];
+                        v |= (prev << bitcount);
+                        data[idx] = v;
+                    }
+                    int v = prev >>> anticount;
+                    data[idx] = v;
+                    if(v==0) {
+                        nWords--;
+                    }
+                    offset++;
+                } else {
+                    int idx = nWords - 1;
+                    int prev = data[idx];
+                    int hi = prev >>> anticount;
+                    int[] result = data;
+                    int[] src = data;
+                    if (hi != 0) {
+                        if(nWords == data.length) {
+                            data = result = new int[nWords + 1];
+                        }
+                        result[nWords++] = hi;
+                    }
+                    leftShift(src,idx,result,bitcount,anticount,prev);
+                }
+            }
+            offset += wordcount;
+            return this;
+        }
+    }
+
+    /**
+     * Returns the number of <code>int</code>s this <code>FDBigInteger</code> represents.
+     *
+     * @return Number of <code>int</code>s required to represent this <code>FDBigInteger</code>.
+     */
+    /*@
+     @ requires this.value() == 0;
+     @ ensures \result == 0;
+     @
+     @  also
+     @
+     @ requires this.value() > 0;
+     @ ensures ((\bigint)1) << (\result - 1) <= this.value() && this.value() <= ((\bigint)1) << \result;
+     @*/
+    private /*@ pure @*/ int size() {
+        return nWords + offset;
+    }
+
+
+    /**
+     * Computes
+     * <pre>
+     * q = (int)( this / S )
+     * this = 10 * ( this mod S )
+     * Return q.
+     * </pre>
+     * This is the iteration step of digit development for output.
+     * We assume that S has been normalized, as above, and that
+     * "this" has been left-shifted accordingly.
+     * Also assumed, of course, is that the result, q, can be expressed
+     * as an integer, {@code 0 <= q < 10}.
+     *
+     * @param S The divisor of this <code>FDBigInteger</code>.
+     * @return <code>q = (int)(this / S)</code>.
+     */
+    /*@
+     @ requires !this.isImmutable;
+     @ requires this.size() <= S.size();
+     @ requires this.data.length + this.offset >= S.size();
+     @ requires S.value() >= ((\bigint)1) << (S.size()*32 - 4);
+     @ assignable this.nWords, this.offset, this.data, this.data[*];
+     @ ensures \result == \old(this.value() / S.value());
+     @ ensures this.value() == \old(10 * (this.value() % S.value()));
+     @*/
+    public int quoRemIteration(FDBigInteger S) throws IllegalArgumentException {
+        assert !this.isImmutable : "cannot modify immutable value";
+        // ensure that this and S have the same number of
+        // digits. If S is properly normalized and q < 10 then
+        // this must be so.
+        int thSize = this.size();
+        int sSize = S.size();
+        if (thSize < sSize) {
+            // this value is significantly less than S, result of division is zero.
+            // just mult this by 10.
+            int p = multAndCarryBy10(this.data, this.nWords, this.data);
+            if(p!=0) {
+                this.data[nWords++] = p;
+            } else {
+                trimLeadingZeros();
+            }
+            return 0;
+        } else if (thSize > sSize) {
+            throw new IllegalArgumentException("disparate values");
+        }
+        // estimate q the obvious way. We will usually be
+        // right. If not, then we're only off by a little and
+        // will re-add.
+        long q = (this.data[this.nWords - 1] & LONG_MASK) / (S.data[S.nWords - 1] & LONG_MASK);
+        long diff = multDiffMe(q, S);
+        if (diff != 0L) {
+            //@ assert q != 0;
+            //@ assert this.offset == \old(Math.min(this.offset, S.offset));
+            //@ assert this.offset <= S.offset;
+
+            // q is too big.
+            // add S back in until this turns +. This should
+            // not be very many times!
+            long sum = 0L;
+            int tStart = S.offset - this.offset;
+            //@ assert tStart >= 0;
+            int[] sd = S.data;
+            int[] td = this.data;
+            while (sum == 0L) {
+                for (int sIndex = 0, tIndex = tStart; tIndex < this.nWords; sIndex++, tIndex++) {
+                    sum += (td[tIndex] & LONG_MASK) + (sd[sIndex] & LONG_MASK);
+                    td[tIndex] = (int) sum;
+                    sum >>>= 32; // Signed or unsigned, answer is 0 or 1
+                }
+                //
+                // Originally the following line read
+                // "if ( sum !=0 && sum != -1 )"
+                // but that would be wrong, because of the
+                // treatment of the two values as entirely unsigned,
+                // it would be impossible for a carry-out to be interpreted
+                // as -1 -- it would have to be a single-bit carry-out, or +1.
+                //
+                assert sum == 0 || sum == 1 : sum; // carry out of division correction
+                q -= 1;
+            }
+        }
+        // finally, we can multiply this by 10.
+        // it cannot overflow, right, as the high-order word has
+        // at least 4 high-order zeros!
+        int p = multAndCarryBy10(this.data, this.nWords, this.data);
+        assert p == 0 : p; // Carry out of *10
+        trimLeadingZeros();
+        return (int) q;
+    }
+
+    /**
+     * Multiplies this <code>FDBigInteger</code> by 10. The operation will be
+     * performed in place unless the <code>FDBigInteger</code> is immutable in
+     * which case a new <code>FDBigInteger</code> will be returned.
+     *
+     * @return The <code>FDBigInteger</code> multiplied by 10.
+     */
+    /*@
+     @ requires this.value() == 0;
+     @ assignable \nothing;
+     @ ensures \result == this;
+     @
+     @  also
+     @
+     @ requires this.value() > 0 && this.isImmutable;
+     @ assignable \nothing;
+     @ ensures \result.value() == \old(this.value() * 10);
+     @
+     @  also
+     @
+     @ requires this.value() > 0 && !this.isImmutable;
+     @ assignable this.nWords, this.data, this.data[*];
+     @ ensures \result == this;
+     @ ensures \result.value() == \old(this.value() * 10);
+     @*/
+    public FDBigInteger multBy10() {
+        if (nWords == 0) {
+            return this;
+        }
+        if (isImmutable) {
+            int[] res = new int[nWords + 1];
+            res[nWords] = multAndCarryBy10(data, nWords, res);
+            return new FDBigInteger(res, offset);
+        } else {
+            int p = multAndCarryBy10(this.data, this.nWords, this.data);
+            if (p != 0) {
+                if (nWords == data.length) {
+                    if (data[0] == 0) {
+                        System.arraycopy(data, 1, data, 0, --nWords);
+                        offset++;
+                    } else {
+                        data = Arrays.copyOf(data, data.length + 1);
+                    }
+                }
+                data[nWords++] = p;
+            } else {
+                trimLeadingZeros();
+            }
+            return this;
+        }
+    }
+
+    /**
+     * Multiplies this <code>FDBigInteger</code> by
+     * <code>5<sup>p5</sup> * 2<sup>p2</sup></code>. The operation will be
+     * performed in place if possible, otherwise a new <code>FDBigInteger</code>
+     * will be returned.
+     *
+     * @param p5 The exponent of the power-of-five factor.
+     * @param p2 The exponent of the power-of-two factor.
+     * @return The multiplication result.
+     */
+    /*@
+     @ requires this.value() == 0 || p5 == 0 && p2 == 0;
+     @ assignable \nothing;
+     @ ensures \result == this;
+     @
+     @  also
+     @
+     @ requires this.value() > 0 && (p5 > 0 && p2 >= 0 || p5 == 0 && p2 > 0 && this.isImmutable);
+     @ assignable \nothing;
+     @ ensures \result.value() == \old(this.value() * pow52(p5, p2));
+     @
+     @  also
+     @
+     @ requires this.value() > 0 && p5 == 0 && p2 > 0 && !this.isImmutable;
+     @ assignable this.nWords, this.data, this.data[*];
+     @ ensures \result == this;
+     @ ensures \result.value() == \old(this.value() * pow52(p5, p2));
+     @*/
+    public FDBigInteger multByPow52(int p5, int p2) {
+        if (this.nWords == 0) {
+            return this;
+        }
+        FDBigInteger res = this;
+        if (p5 != 0) {
+            int[] r;
+            int extraSize = (p2 != 0) ? 1 : 0;
+            if (p5 < SMALL_5_POW.length) {
+                r = new int[this.nWords + 1 + extraSize];
+                mult(this.data, this.nWords, SMALL_5_POW[p5], r);
+                res = new FDBigInteger(r, this.offset);
+            } else {
+                FDBigInteger pow5 = big5pow(p5);
+                r = new int[this.nWords + pow5.size() + extraSize];
+                mult(this.data, this.nWords, pow5.data, pow5.nWords, r);
+                res = new FDBigInteger(r, this.offset + pow5.offset);
+            }
+        }
+        return res.leftShift(p2);
+    }
+
+    /**
+     * Multiplies two big integers represented as int arrays.
+     *
+     * @param s1 The first array factor.
+     * @param s1Len The number of elements of <code>s1</code> to use.
+     * @param s2 The second array factor.
+     * @param s2Len The number of elements of <code>s2</code> to use.
+     * @param dst The product array.
+     */
+    /*@
+     @ requires s1 != dst && s2 != dst;
+     @ requires s1.length >= s1Len && s2.length >= s2Len && dst.length >= s1Len + s2Len;
+     @ assignable dst[0 .. s1Len + s2Len - 1];
+     @ ensures AP(dst, s1Len + s2Len) == \old(AP(s1, s1Len) * AP(s2, s2Len));
+     @*/
+    private static void mult(int[] s1, int s1Len, int[] s2, int s2Len, int[] dst) {
+        for (int i = 0; i < s1Len; i++) {
+            long v = s1[i] & LONG_MASK;
+            long p = 0L;
+            for (int j = 0; j < s2Len; j++) {
+                p += (dst[i + j] & LONG_MASK) + v * (s2[j] & LONG_MASK);
+                dst[i + j] = (int) p;
+                p >>>= 32;
+            }
+            dst[i + s2Len] = (int) p;
+        }
+    }
+
+    /**
+     * Subtracts the supplied <code>FDBigInteger</code> subtrahend from this
+     * <code>FDBigInteger</code>. Assert that the result is positive.
+     * If the subtrahend is immutable, store the result in this(minuend).
+     * If this(minuend) is immutable a new <code>FDBigInteger</code> is created.
+     *
+     * @param subtrahend The <code>FDBigInteger</code> to be subtracted.
+     * @return This <code>FDBigInteger</code> less the subtrahend.
+     */
+    /*@
+     @ requires this.isImmutable;
+     @ requires this.value() >= subtrahend.value();
+     @ assignable \nothing;
+     @ ensures \result.value() == \old(this.value() - subtrahend.value());
+     @
+     @  also
+     @
+     @ requires !subtrahend.isImmutable;
+     @ requires this.value() >= subtrahend.value();
+     @ assignable this.nWords, this.offset, this.data, this.data[*];
+     @ ensures \result == this;
+     @ ensures \result.value() == \old(this.value() - subtrahend.value());
+     @*/
+    public FDBigInteger leftInplaceSub(FDBigInteger subtrahend) {
+        assert this.size() >= subtrahend.size() : "result should be positive";
+        FDBigInteger minuend;
+        if (this.isImmutable) {
+            minuend = new FDBigInteger(this.data.clone(), this.offset);
+        } else {
+            minuend = this;
+        }
+        int offsetDiff = subtrahend.offset - minuend.offset;
+        int[] sData = subtrahend.data;
+        int[] mData = minuend.data;
+        int subLen = subtrahend.nWords;
+        int minLen = minuend.nWords;
+        if (offsetDiff < 0) {
+            // need to expand minuend
+            int rLen = minLen - offsetDiff;
+            if (rLen < mData.length) {
+                System.arraycopy(mData, 0, mData, -offsetDiff, minLen);
+                Arrays.fill(mData, 0, -offsetDiff, 0);
+            } else {
+                int[] r = new int[rLen];
+                System.arraycopy(mData, 0, r, -offsetDiff, minLen);
+                minuend.data = mData = r;
+            }
+            minuend.offset = subtrahend.offset;
+            minuend.nWords = minLen = rLen;
+            offsetDiff = 0;
+        }
+        long borrow = 0L;
+        int mIndex = offsetDiff;
+        for (int sIndex = 0; sIndex < subLen && mIndex < minLen; sIndex++, mIndex++) {
+            long diff = (mData[mIndex] & LONG_MASK) - (sData[sIndex] & LONG_MASK) + borrow;
+            mData[mIndex] = (int) diff;
+            borrow = diff >> 32; // signed shift
+        }
+        for (; borrow != 0 && mIndex < minLen; mIndex++) {
+            long diff = (mData[mIndex] & LONG_MASK) + borrow;
+            mData[mIndex] = (int) diff;
+            borrow = diff >> 32; // signed shift
+        }
+        assert borrow == 0L : borrow; // borrow out of subtract,
+        // result should be positive
+        minuend.trimLeadingZeros();
+        return minuend;
+    }
+
+    /**
+     * Subtracts the supplied <code>FDBigInteger</code> subtrahend from this
+     * <code>FDBigInteger</code>. Assert that the result is positive.
+     * If the this(minuend) is immutable, store the result in subtrahend.
+     * If subtrahend is immutable a new <code>FDBigInteger</code> is created.
+     *
+     * @param subtrahend The <code>FDBigInteger</code> to be subtracted.
+     * @return This <code>FDBigInteger</code> less the subtrahend.
+     */
+    /*@
+     @ requires subtrahend.isImmutable;
+     @ requires this.value() >= subtrahend.value();
+     @ assignable \nothing;
+     @ ensures \result.value() == \old(this.value() - subtrahend.value());
+     @
+     @  also
+     @
+     @ requires !subtrahend.isImmutable;
+     @ requires this.value() >= subtrahend.value();
+     @ assignable subtrahend.nWords, subtrahend.offset, subtrahend.data, subtrahend.data[*];
+     @ ensures \result == subtrahend;
+     @ ensures \result.value() == \old(this.value() - subtrahend.value());
+     @*/
+    public FDBigInteger rightInplaceSub(FDBigInteger subtrahend) {
+        assert this.size() >= subtrahend.size() : "result should be positive";
+        FDBigInteger minuend = this;
+        if (subtrahend.isImmutable) {
+            subtrahend = new FDBigInteger(subtrahend.data.clone(), subtrahend.offset);
+        }
+        int offsetDiff = minuend.offset - subtrahend.offset;
+        int[] sData = subtrahend.data;
+        int[] mData = minuend.data;
+        int subLen = subtrahend.nWords;
+        int minLen = minuend.nWords;
+        if (offsetDiff < 0) {
+            int rLen = minLen;
+            if (rLen < sData.length) {
+                System.arraycopy(sData, 0, sData, -offsetDiff, subLen);
+                Arrays.fill(sData, 0, -offsetDiff, 0);
+            } else {
+                int[] r = new int[rLen];
+                System.arraycopy(sData, 0, r, -offsetDiff, subLen);
+                subtrahend.data = sData = r;
+            }
+            subtrahend.offset = minuend.offset;
+            subLen -= offsetDiff;
+            offsetDiff = 0;
+        } else {
+            int rLen = minLen + offsetDiff;
+            if (rLen >= sData.length) {
+                subtrahend.data = sData = Arrays.copyOf(sData, rLen);
+            }
+        }
+        //@ assert minuend == this && minuend.value() == \old(this.value());
+        //@ assert mData == minuend.data && minLen == minuend.nWords;
+        //@ assert subtrahend.offset + subtrahend.data.length >= minuend.size();
+        //@ assert sData == subtrahend.data;
+        //@ assert AP(subtrahend.data, subtrahend.data.length) << subtrahend.offset == \old(subtrahend.value());
+        //@ assert subtrahend.offset == Math.min(\old(this.offset), minuend.offset);
+        //@ assert offsetDiff == minuend.offset - subtrahend.offset;
+        //@ assert 0 <= offsetDiff && offsetDiff + minLen <= sData.length;
+        int sIndex = 0;
+        long borrow = 0L;
+        for (; sIndex < offsetDiff; sIndex++) {
+            long diff = 0L - (sData[sIndex] & LONG_MASK) + borrow;
+            sData[sIndex] = (int) diff;
+            borrow = diff >> 32; // signed shift
+        }
+        //@ assert sIndex == offsetDiff;
+        for (int mIndex = 0; mIndex < minLen; sIndex++, mIndex++) {
+            //@ assert sIndex == offsetDiff + mIndex;
+            long diff = (mData[mIndex] & LONG_MASK) - (sData[sIndex] & LONG_MASK) + borrow;
+            sData[sIndex] = (int) diff;
+            borrow = diff >> 32; // signed shift
+        }
+        assert borrow == 0L : borrow; // borrow out of subtract,
+        // result should be positive
+        subtrahend.nWords = sIndex;
+        subtrahend.trimLeadingZeros();
+        return subtrahend;
+
+    }
+
+    /**
+     * Determines whether all elements of an array are zero for all indices less
+     * than a given index.
+     *
+     * @param a The array to be examined.
+     * @param from The index strictly below which elements are to be examined.
+     * @return Zero if all elements in range are zero, 1 otherwise.
+     */
+    /*@
+     @ requires 0 <= from && from <= a.length;
+     @ ensures \result == (AP(a, from) == 0 ? 0 : 1);
+     @*/
+    private /*@ pure @*/ static int checkZeroTail(int[] a, int from) {
+        while (from > 0) {
+            if (a[--from] != 0) {
+                return 1;
+            }
+        }
+        return 0;
+    }
+
+    /**
+     * Compares the parameter with this <code>FDBigInteger</code>. Returns an
+     * integer accordingly as:
+     * <pre>{@code
+     * > 0: this > other
+     *   0: this == other
+     * < 0: this < other
+     * }</pre>
+     *
+     * @param other The <code>FDBigInteger</code> to compare.
+     * @return A negative value, zero, or a positive value according to the
+     * result of the comparison.
+     */
+    /*@
+     @ ensures \result == (this.value() < other.value() ? -1 : this.value() > other.value() ? +1 : 0);
+     @*/
+    public /*@ pure @*/ int cmp(FDBigInteger other) {
+        int aSize = nWords + offset;
+        int bSize = other.nWords + other.offset;
+        if (aSize > bSize) {
+            return 1;
+        } else if (aSize < bSize) {
+            return -1;
+        }
+        int aLen = nWords;
+        int bLen = other.nWords;
+        while (aLen > 0 && bLen > 0) {
+            int a = data[--aLen];
+            int b = other.data[--bLen];
+            if (a != b) {
+                return ((a & LONG_MASK) < (b & LONG_MASK)) ? -1 : 1;
+            }
+        }
+        if (aLen > 0) {
+            return checkZeroTail(data, aLen);
+        }
+        if (bLen > 0) {
+            return -checkZeroTail(other.data, bLen);
+        }
+        return 0;
+    }
+
+    /**
+     * Compares this <code>FDBigInteger</code> with
+     * <code>5<sup>p5</sup> * 2<sup>p2</sup></code>.
+     * Returns an integer accordingly as:
+     * <pre>{@code
+     * > 0: this > other
+     *   0: this == other
+     * < 0: this < other
+     * }</pre>
+     * @param p5 The exponent of the power-of-five factor.
+     * @param p2 The exponent of the power-of-two factor.
+     * @return A negative value, zero, or a positive value according to the
+     * result of the comparison.
+     */
+    /*@
+     @ requires p5 >= 0 && p2 >= 0;
+     @ ensures \result == (this.value() < pow52(p5, p2) ? -1 : this.value() >  pow52(p5, p2) ? +1 : 0);
+     @*/
+    public /*@ pure @*/ int cmpPow52(int p5, int p2) {
+        if (p5 == 0) {
+            int wordcount = p2 >> 5;
+            int bitcount = p2 & 0x1f;
+            int size = this.nWords + this.offset;
+            if (size > wordcount + 1) {
+                return 1;
+            } else if (size < wordcount + 1) {
+                return -1;
+            }
+            int a = this.data[this.nWords -1];
+            int b = 1 << bitcount;
+            if (a != b) {
+                return ( (a & LONG_MASK) < (b & LONG_MASK)) ? -1 : 1;
+            }
+            return checkZeroTail(this.data, this.nWords - 1);
+        }
+        return this.cmp(big5pow(p5).leftShift(p2));
+    }
+
+    /**
+     * Compares this <code>FDBigInteger</code> with <code>x + y</code>. Returns a
+     * value according to the comparison as:
+     * <pre>{@code
+     * -1: this <  x + y
+     *  0: this == x + y
+     *  1: this >  x + y
+     * }</pre>
+     * @param x The first addend of the sum to compare.
+     * @param y The second addend of the sum to compare.
+     * @return -1, 0, or 1 according to the result of the comparison.
+     */
+    /*@
+     @ ensures \result == (this.value() < x.value() + y.value() ? -1 : this.value() > x.value() + y.value() ? +1 : 0);
+     @*/
+    public /*@ pure @*/ int addAndCmp(FDBigInteger x, FDBigInteger y) {
+        FDBigInteger big;
+        FDBigInteger small;
+        int xSize = x.size();
+        int ySize = y.size();
+        int bSize;
+        int sSize;
+        if (xSize >= ySize) {
+            big = x;
+            small = y;
+            bSize = xSize;
+            sSize = ySize;
+        } else {
+            big = y;
+            small = x;
+            bSize = ySize;
+            sSize = xSize;
+        }
+        int thSize = this.size();
+        if (bSize == 0) {
+            return thSize == 0 ? 0 : 1;
+        }
+        if (sSize == 0) {
+            return this.cmp(big);
+        }
+        if (bSize > thSize) {
+            return -1;
+        }
+        if (bSize + 1 < thSize) {
+            return 1;
+        }
+        long top = (big.data[big.nWords - 1] & LONG_MASK);
+        if (sSize == bSize) {
+            top += (small.data[small.nWords - 1] & LONG_MASK);
+        }
+        if ((top >>> 32) == 0) {
+            if (((top + 1) >>> 32) == 0) {
+                // good case - no carry extension
+                if (bSize < thSize) {
+                    return 1;
+                }
+                // here sum.nWords == this.nWords
+                long v = (this.data[this.nWords - 1] & LONG_MASK);
+                if (v < top) {
+                    return -1;
+                }
+                if (v > top + 1) {
+                    return 1;
+                }
+            }
+        } else { // (top>>>32)!=0 guaranteed carry extension
+            if (bSize + 1 > thSize) {
+                return -1;
+            }
+            // here sum.nWords == this.nWords
+            top >>>= 32;
+            long v = (this.data[this.nWords - 1] & LONG_MASK);
+            if (v < top) {
+                return -1;
+            }
+            if (v > top + 1) {
+                return 1;
+            }
+        }
+        return this.cmp(big.add(small));
+    }
+
+    /**
+     * Makes this <code>FDBigInteger</code> immutable.
+     */
+    /*@
+     @ assignable this.isImmutable;
+     @ ensures this.isImmutable;
+     @*/
+    public void makeImmutable() {
+        this.isImmutable = true;
+    }
+
+    /**
+     * Multiplies this <code>FDBigInteger</code> by an integer.
+     *
+     * @param i The factor by which to multiply this <code>FDBigInteger</code>.
+     * @return This <code>FDBigInteger</code> multiplied by an integer.
+     */
+    /*@
+     @ requires this.value() == 0;
+     @ assignable \nothing;
+     @ ensures \result == this;
+     @
+     @  also
+     @
+     @ requires this.value() != 0;
+     @ assignable \nothing;
+     @ ensures \result.value() == \old(this.value() * UNSIGNED(i));
+     @*/
+    private FDBigInteger mult(int i) {
+        if (this.nWords == 0) {
+            return this;
+        }
+        int[] r = new int[nWords + 1];
+        mult(data, nWords, i, r);
+        return new FDBigInteger(r, offset);
+    }
+
+    /**
+     * Multiplies this <code>FDBigInteger</code> by another <code>FDBigInteger</code>.
+     *
+     * @param other The <code>FDBigInteger</code> factor by which to multiply.
+     * @return The product of this and the parameter <code>FDBigInteger</code>s.
+     */
+    /*@
+     @ requires this.value() == 0;
+     @ assignable \nothing;
+     @ ensures \result == this;
+     @
+     @  also
+     @
+     @ requires this.value() != 0 && other.value() == 0;
+     @ assignable \nothing;
+     @ ensures \result == other;
+     @
+     @  also
+     @
+     @ requires this.value() != 0 && other.value() != 0;
+     @ assignable \nothing;
+     @ ensures \result.value() == \old(this.value() * other.value());
+     @*/
+    private FDBigInteger mult(FDBigInteger other) {
+        if (this.nWords == 0) {
+            return this;
+        }
+        if (this.size() == 1) {
+            return other.mult(data[0]);
+        }
+        if (other.nWords == 0) {
+            return other;
+        }
+        if (other.size() == 1) {
+            return this.mult(other.data[0]);
+        }
+        int[] r = new int[nWords + other.nWords];
+        mult(this.data, this.nWords, other.data, other.nWords, r);
+        return new FDBigInteger(r, this.offset + other.offset);
+    }
+
+    /**
+     * Adds another <code>FDBigInteger</code> to this <code>FDBigInteger</code>.
+     *
+     * @param other The <code>FDBigInteger</code> to add.
+     * @return The sum of the <code>FDBigInteger</code>s.
+     */
+    /*@
+     @ assignable \nothing;
+     @ ensures \result.value() == \old(this.value() + other.value());
+     @*/
+    private FDBigInteger add(FDBigInteger other) {
+        FDBigInteger big, small;
+        int bigLen, smallLen;
+        int tSize = this.size();
+        int oSize = other.size();
+        if (tSize >= oSize) {
+            big = this;
+            bigLen = tSize;
+            small = other;
+            smallLen = oSize;
+        } else {
+            big = other;
+            bigLen = oSize;
+            small = this;
+            smallLen = tSize;
+        }
+        int[] r = new int[bigLen + 1];
+        int i = 0;
+        long carry = 0L;
+        for (; i < smallLen; i++) {
+            carry += (i < big.offset   ? 0L : (big.data[i - big.offset] & LONG_MASK) )
+                   + ((i < small.offset ? 0L : (small.data[i - small.offset] & LONG_MASK)));
+            r[i] = (int) carry;
+            carry >>= 32; // signed shift.
+        }
+        for (; i < bigLen; i++) {
+            carry += (i < big.offset ? 0L : (big.data[i - big.offset] & LONG_MASK) );
+            r[i] = (int) carry;
+            carry >>= 32; // signed shift.
+        }
+        r[bigLen] = (int) carry;
+        return new FDBigInteger(r, 0);
+    }
+
+
+    /**
+     * Multiplies a <code>FDBigInteger</code> by an int and adds another int. The
+     * result is computed in place. This method is intended only to be invoked
+     * from
+     * <code>
+     * FDBigInteger(long lValue, char[] digits, int kDigits, int nDigits)
+     * </code>.
+     *
+     * @param iv The factor by which to multiply this <code>FDBigInteger</code>.
+     * @param addend The value to add to the product of this
+     * <code>FDBigInteger</code> and <code>iv</code>.
+     */
+    /*@
+     @ requires this.value()*UNSIGNED(iv) + UNSIGNED(addend) < ((\bigint)1) << ((this.data.length + this.offset)*32);
+     @ assignable this.data[*];
+     @ ensures this.value() == \old(this.value()*UNSIGNED(iv) + UNSIGNED(addend));
+     @*/
+    private /*@ helper @*/ void multAddMe(int iv, int addend) {
+        long v = iv & LONG_MASK;
+        // unroll 0th iteration, doing addition.
+        long p = v * (data[0] & LONG_MASK) + (addend & LONG_MASK);
+        data[0] = (int) p;
+        p >>>= 32;
+        for (int i = 1; i < nWords; i++) {
+            p += v * (data[i] & LONG_MASK);
+            data[i] = (int) p;
+            p >>>= 32;
+        }
+        if (p != 0L) {
+            data[nWords++] = (int) p; // will fail noisily if illegal!
+        }
+    }
+
+    //
+    // original doc:
+    //
+    // do this -=q*S
+    // returns borrow
+    //
+    /**
+     * Multiplies the parameters and subtracts them from this
+     * <code>FDBigInteger</code>.
+     *
+     * @param q The integer parameter.
+     * @param S The <code>FDBigInteger</code> parameter.
+     * @return <code>this - q*S</code>.
+     */
+    /*@
+     @ ensures nWords == 0 ==> offset == 0;
+     @ ensures nWords > 0 ==> data[nWords - 1] != 0;
+     @*/
+    /*@
+     @ requires 0 < q && q <= (1L << 31);
+     @ requires data != null;
+     @ requires 0 <= nWords && nWords <= data.length && offset >= 0;
+     @ requires !this.isImmutable;
+     @ requires this.size() == S.size();
+     @ requires this != S;
+     @ assignable this.nWords, this.offset, this.data, this.data[*];
+     @ ensures -q <= \result && \result <= 0;
+     @ ensures this.size() == \old(this.size());
+     @ ensures this.value() + (\result << (this.size()*32)) == \old(this.value() - q*S.value());
+     @ ensures this.offset == \old(Math.min(this.offset, S.offset));
+     @ ensures \old(this.offset <= S.offset) ==> this.nWords == \old(this.nWords);
+     @ ensures \old(this.offset <= S.offset) ==> this.offset == \old(this.offset);
+     @ ensures \old(this.offset <= S.offset) ==> this.data == \old(this.data);
+     @
+     @  also
+     @
+     @ requires q == 0;
+     @ assignable \nothing;
+     @ ensures \result == 0;
+     @*/
+    private /*@ helper @*/ long multDiffMe(long q, FDBigInteger S) {
+        long diff = 0L;
+        if (q != 0) {
+            int deltaSize = S.offset - this.offset;
+            if (deltaSize >= 0) {
+                int[] sd = S.data;
+                int[] td = this.data;
+                for (int sIndex = 0, tIndex = deltaSize; sIndex < S.nWords; sIndex++, tIndex++) {
+                    diff += (td[tIndex] & LONG_MASK) - q * (sd[sIndex] & LONG_MASK);
+                    td[tIndex] = (int) diff;
+                    diff >>= 32; // N.B. SIGNED shift.
+                }
+            } else {
+                deltaSize = -deltaSize;
+                int[] rd = new int[nWords + deltaSize];
+                int sIndex = 0;
+                int rIndex = 0;
+                int[] sd = S.data;
+                for (; rIndex < deltaSize && sIndex < S.nWords; sIndex++, rIndex++) {
+                    diff -= q * (sd[sIndex] & LONG_MASK);
+                    rd[rIndex] = (int) diff;
+                    diff >>= 32; // N.B. SIGNED shift.
+                }
+                int tIndex = 0;
+                int[] td = this.data;
+                for (; sIndex < S.nWords; sIndex++, tIndex++, rIndex++) {
+                    diff += (td[tIndex] & LONG_MASK) - q * (sd[sIndex] & LONG_MASK);
+                    rd[rIndex] = (int) diff;
+                    diff >>= 32; // N.B. SIGNED shift.
+                }
+                this.nWords += deltaSize;
+                this.offset -= deltaSize;
+                this.data = rd;
+            }
+        }
+        return diff;
+    }
+
+
+    /**
+     * Multiplies by 10 a big integer represented as an array. The final carry
+     * is returned.
+     *
+     * @param src The array representation of the big integer.
+     * @param srcLen The number of elements of <code>src</code> to use.
+     * @param dst The product array.
+     * @return The final carry of the multiplication.
+     */
+    /*@
+     @ requires src.length >= srcLen && dst.length >= srcLen;
+     @ assignable dst[0 .. srcLen - 1];
+     @ ensures 0 <= \result && \result < 10;
+     @ ensures AP(dst, srcLen) + (\result << (srcLen*32)) == \old(AP(src, srcLen) * 10);
+     @*/
+    private static int multAndCarryBy10(int[] src, int srcLen, int[] dst) {
+        long carry = 0;
+        for (int i = 0; i < srcLen; i++) {
+            long product = (src[i] & LONG_MASK) * 10L + carry;
+            dst[i] = (int) product;
+            carry = product >>> 32;
+        }
+        return (int) carry;
+    }
+
+    /**
+     * Multiplies by a constant value a big integer represented as an array.
+     * The constant factor is an <code>int</code>.
+     *
+     * @param src The array representation of the big integer.
+     * @param srcLen The number of elements of <code>src</code> to use.
+     * @param value The constant factor by which to multiply.
+     * @param dst The product array.
+     */
+    /*@
+     @ requires src.length >= srcLen && dst.length >= srcLen + 1;
+     @ assignable dst[0 .. srcLen];
+     @ ensures AP(dst, srcLen + 1) == \old(AP(src, srcLen) * UNSIGNED(value));
+     @*/
+    private static void mult(int[] src, int srcLen, int value, int[] dst) {
+        long val = value & LONG_MASK;
+        long carry = 0;
+        for (int i = 0; i < srcLen; i++) {
+            long product = (src[i] & LONG_MASK) * val + carry;
+            dst[i] = (int) product;
+            carry = product >>> 32;
+        }
+        dst[srcLen] = (int) carry;
+    }
+
+    /**
+     * Multiplies by a constant value a big integer represented as an array.
+     * The constant factor is a long represent as two <code>int</code>s.
+     *
+     * @param src The array representation of the big integer.
+     * @param srcLen The number of elements of <code>src</code> to use.
+     * @param v0 The lower 32 bits of the long factor.
+     * @param v1 The upper 32 bits of the long factor.
+     * @param dst The product array.
+     */
+    /*@
+     @ requires src != dst;
+     @ requires src.length >= srcLen && dst.length >= srcLen + 2;
+     @ assignable dst[0 .. srcLen + 1];
+     @ ensures AP(dst, srcLen + 2) == \old(AP(src, srcLen) * (UNSIGNED(v0) + (UNSIGNED(v1) << 32)));
+     @*/
+    private static void mult(int[] src, int srcLen, int v0, int v1, int[] dst) {
+        long v = v0 & LONG_MASK;
+        long carry = 0;
+        for (int j = 0; j < srcLen; j++) {
+            long product = v * (src[j] & LONG_MASK) + carry;
+            dst[j] = (int) product;
+            carry = product >>> 32;
+        }
+        dst[srcLen] = (int) carry;
+        v = v1 & LONG_MASK;
+        carry = 0;
+        for (int j = 0; j < srcLen; j++) {
+            long product = (dst[j + 1] & LONG_MASK) + v * (src[j] & LONG_MASK) + carry;
+            dst[j + 1] = (int) product;
+            carry = product >>> 32;
+        }
+        dst[srcLen + 1] = (int) carry;
+    }
+
+    // Fails assertion for negative exponent.
+    /**
+     * Computes <code>5</code> raised to a given power.
+     *
+     * @param p The exponent of 5.
+     * @return <code>5<sup>p</sup></code>.
+     */
+    private static FDBigInteger big5pow(int p) {
+        assert p >= 0 : p; // negative power of 5
+        if (p < MAX_FIVE_POW) {
+            return POW_5_CACHE[p];
+        }
+        return big5powRec(p);
+    }
+
+    // slow path
+    /**
+     * Computes <code>5</code> raised to a given power.
+     *
+     * @param p The exponent of 5.
+     * @return <code>5<sup>p</sup></code>.
+     */
+    private static FDBigInteger big5powRec(int p) {
+        if (p < MAX_FIVE_POW) {
+            return POW_5_CACHE[p];
+        }
+        // construct the value.
+        // recursively.
+        int q, r;
+        // in order to compute 5^p,
+        // compute its square root, 5^(p/2) and square.
+        // or, let q = p / 2, r = p -q, then
+        // 5^p = 5^(q+r) = 5^q * 5^r
+        q = p >> 1;
+        r = p - q;
+        FDBigInteger bigq = big5powRec(q);
+        if (r < SMALL_5_POW.length) {
+            return bigq.mult(SMALL_5_POW[r]);
+        } else {
+            return bigq.mult(big5powRec(r));
+        }
+    }
+
+    // for debugging ...
+    /**
+     * Converts this <code>FDBigInteger</code> to a hexadecimal string.
+     *
+     * @return The hexadecimal string representation.
+     */
+    public String toHexString(){
+        if(nWords ==0) {
+            return "0";
+        }
+        StringBuilder sb = new StringBuilder((nWords +offset)*8);
+        for(int i= nWords -1; i>=0; i--) {
+            String subStr = Integer.toHexString(data[i]);
+            for(int j = subStr.length(); j<8; j++) {
+                sb.append('0');
+            }
+            sb.append(subStr);
+        }
+        for(int i=offset; i>0; i--) {
+            sb.append("00000000");
+        }
+        return sb.toString();
+    }
+
+    // for debugging ...
+    /**
+     * Converts this <code>FDBigInteger</code> to a <code>BigInteger</code>.
+     *
+     * @return The <code>BigInteger</code> representation.
+     */
+    public BigInteger toBigInteger() {
+        byte[] magnitude = new byte[nWords * 4 + 1];
+        for (int i = 0; i < nWords; i++) {
+            int w = data[i];
+            magnitude[magnitude.length - 4 * i - 1] = (byte) w;
+            magnitude[magnitude.length - 4 * i - 2] = (byte) (w >> 8);
+            magnitude[magnitude.length - 4 * i - 3] = (byte) (w >> 16);
+            magnitude[magnitude.length - 4 * i - 4] = (byte) (w >> 24);
+        }
+        return new BigInteger(magnitude).shiftLeft(offset * 32);
+    }
+
+    // for debugging ...
+    /**
+     * Converts this <code>FDBigInteger</code> to a string.
+     *
+     * @return The string representation.
+     */
+    @Override
+    public String toString(){
+        return toBigInteger().toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/math/FloatConsts.java	Tue Dec 22 09:14:16 2015 -0800
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.math;
+
+/**
+ * This class contains additional constants documenting limits of the
+ * <code>float</code> type.
+ *
+ * @author Joseph D. Darcy
+ */
+
+public class FloatConsts {
+    /**
+     * Don't let anyone instantiate this class.
+     */
+    private FloatConsts() {}
+
+    public static final float POSITIVE_INFINITY = java.lang.Float.POSITIVE_INFINITY;
+    public static final float NEGATIVE_INFINITY = java.lang.Float.NEGATIVE_INFINITY;
+    public static final float NaN = java.lang.Float.NaN;
+    public static final float MAX_VALUE = java.lang.Float.MAX_VALUE;
+    public static final float MIN_VALUE = java.lang.Float.MIN_VALUE;
+
+    /**
+     * A constant holding the smallest positive normal value of type
+     * <code>float</code>, 2<sup>-126</sup>.  It is equal to the value
+     * returned by <code>Float.intBitsToFloat(0x00800000)</code>.
+     */
+    public static final float   MIN_NORMAL      = 1.17549435E-38f;
+
+    /**
+     * The number of logical bits in the significand of a
+     * <code>float</code> number, including the implicit bit.
+     */
+    public static final int SIGNIFICAND_WIDTH   = 24;
+
+    /**
+     * Maximum exponent a finite <code>float</code> number may have.
+     * It is equal to the value returned by
+     * <code>Math.ilogb(Float.MAX_VALUE)</code>.
+     */
+    public static final int     MAX_EXPONENT    = 127;
+
+    /**
+     * Minimum exponent a normalized <code>float</code> number may
+     * have.  It is equal to the value returned by
+     * <code>Math.ilogb(Float.MIN_NORMAL)</code>.
+     */
+    public static final int     MIN_EXPONENT    = -126;
+
+    /**
+     * The exponent the smallest positive <code>float</code> subnormal
+     * value would have if it could be normalized.
+     */
+    public static final int     MIN_SUB_EXPONENT = MIN_EXPONENT -
+                                                   (SIGNIFICAND_WIDTH - 1);
+
+    /**
+     * Bias used in representing a <code>float</code> exponent.
+     */
+    public static final int     EXP_BIAS        = 127;
+
+    /**
+     * Bit mask to isolate the sign bit of a <code>float</code>.
+     */
+    public static final int     SIGN_BIT_MASK   = 0x80000000;
+
+    /**
+     * Bit mask to isolate the exponent field of a
+     * <code>float</code>.
+     */
+    public static final int     EXP_BIT_MASK    = 0x7F800000;
+
+    /**
+     * Bit mask to isolate the significand field of a
+     * <code>float</code>.
+     */
+    public static final int     SIGNIF_BIT_MASK = 0x007FFFFF;
+
+    static {
+        // verify bit masks cover all bit positions and that the bit
+        // masks are non-overlapping
+        assert(((SIGN_BIT_MASK | EXP_BIT_MASK | SIGNIF_BIT_MASK) == ~0) &&
+               (((SIGN_BIT_MASK & EXP_BIT_MASK) == 0) &&
+                ((SIGN_BIT_MASK & SIGNIF_BIT_MASK) == 0) &&
+                ((EXP_BIT_MASK & SIGNIF_BIT_MASK) == 0)));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/math/FloatingDecimal.java	Tue Dec 22 09:14:16 2015 -0800
@@ -0,0 +1,2552 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.math;
+
+import java.util.Arrays;
+import java.util.regex.*;
+
+/**
+ * A class for converting between ASCII and decimal representations of a single
+ * or double precision floating point number. Most conversions are provided via
+ * static convenience methods, although a <code>BinaryToASCIIConverter</code>
+ * instance may be obtained and reused.
+ */
+public class FloatingDecimal{
+    //
+    // Constants of the implementation;
+    // most are IEEE-754 related.
+    // (There are more really boring constants at the end.)
+    //
+    static final int    EXP_SHIFT = DoubleConsts.SIGNIFICAND_WIDTH - 1;
+    static final long   FRACT_HOB = ( 1L<<EXP_SHIFT ); // assumed High-Order bit
+    static final long   EXP_ONE   = ((long)DoubleConsts.EXP_BIAS)<<EXP_SHIFT; // exponent of 1.0
+    static final int    MAX_SMALL_BIN_EXP = 62;
+    static final int    MIN_SMALL_BIN_EXP = -( 63 / 3 );
+    static final int    MAX_DECIMAL_DIGITS = 15;
+    static final int    MAX_DECIMAL_EXPONENT = 308;
+    static final int    MIN_DECIMAL_EXPONENT = -324;
+    static final int    BIG_DECIMAL_EXPONENT = 324; // i.e. abs(MIN_DECIMAL_EXPONENT)
+    static final int    MAX_NDIGITS = 1100;
+
+    static final int    SINGLE_EXP_SHIFT  =   FloatConsts.SIGNIFICAND_WIDTH - 1;
+    static final int    SINGLE_FRACT_HOB  =   1<<SINGLE_EXP_SHIFT;
+    static final int    SINGLE_MAX_DECIMAL_DIGITS = 7;
+    static final int    SINGLE_MAX_DECIMAL_EXPONENT = 38;
+    static final int    SINGLE_MIN_DECIMAL_EXPONENT = -45;
+    static final int    SINGLE_MAX_NDIGITS = 200;
+
+    static final int    INT_DECIMAL_DIGITS = 9;
+
+    /**
+     * Converts a double precision floating point value to a <code>String</code>.
+     *
+     * @param d The double precision value.
+     * @return The value converted to a <code>String</code>.
+     */
+    public static String toJavaFormatString(double d) {
+        return getBinaryToASCIIConverter(d).toJavaFormatString();
+    }
+
+    /**
+     * Converts a single precision floating point value to a <code>String</code>.
+     *
+     * @param f The single precision value.
+     * @return The value converted to a <code>String</code>.
+     */
+    public static String toJavaFormatString(float f) {
+        return getBinaryToASCIIConverter(f).toJavaFormatString();
+    }
+
+    /**
+     * Appends a double precision floating point value to an <code>Appendable</code>.
+     * @param d The double precision value.
+     * @param buf The <code>Appendable</code> with the value appended.
+     */
+    public static void appendTo(double d, Appendable buf) {
+        getBinaryToASCIIConverter(d).appendTo(buf);
+    }
+
+    /**
+     * Appends a single precision floating point value to an <code>Appendable</code>.
+     * @param f The single precision value.
+     * @param buf The <code>Appendable</code> with the value appended.
+     */
+    public static void appendTo(float f, Appendable buf) {
+        getBinaryToASCIIConverter(f).appendTo(buf);
+    }
+
+    /**
+     * Converts a <code>String</code> to a double precision floating point value.
+     *
+     * @param s The <code>String</code> to convert.
+     * @return The double precision value.
+     * @throws NumberFormatException If the <code>String</code> does not
+     * represent a properly formatted double precision value.
+     */
+    public static double parseDouble(String s) throws NumberFormatException {
+        return readJavaFormatString(s).doubleValue();
+    }
+
+    /**
+     * Converts a <code>String</code> to a single precision floating point value.
+     *
+     * @param s The <code>String</code> to convert.
+     * @return The single precision value.
+     * @throws NumberFormatException If the <code>String</code> does not
+     * represent a properly formatted single precision value.
+     */
+    public static float parseFloat(String s) throws NumberFormatException {
+        return readJavaFormatString(s).floatValue();
+    }
+
+    /**
+     * A converter which can process single or double precision floating point
+     * values into an ASCII <code>String</code> representation.
+     */
+    public interface BinaryToASCIIConverter {
+        /**
+         * Converts a floating point value into an ASCII <code>String</code>.
+         * @return The value converted to a <code>String</code>.
+         */
+        public String toJavaFormatString();
+
+        /**
+         * Appends a floating point value to an <code>Appendable</code>.
+         * @param buf The <code>Appendable</code> to receive the value.
+         */
+        public void appendTo(Appendable buf);
+
+        /**
+         * Retrieves the decimal exponent most closely corresponding to this value.
+         * @return The decimal exponent.
+         */
+        public int getDecimalExponent();
+
+        /**
+         * Retrieves the value as an array of digits.
+         * @param digits The digit array.
+         * @return The number of valid digits copied into the array.
+         */
+        public int getDigits(char[] digits);
+
+        /**
+         * Indicates the sign of the value.
+         * @return {@code value < 0.0}.
+         */
+        public boolean isNegative();
+
+        /**
+         * Indicates whether the value is either infinite or not a number.
+         *
+         * @return <code>true</code> if and only if the value is <code>NaN</code>
+         * or infinite.
+         */
+        public boolean isExceptional();
+
+        /**
+         * Indicates whether the value was rounded up during the binary to ASCII
+         * conversion.
+         *
+         * @return <code>true</code> if and only if the value was rounded up.
+         */
+        public boolean digitsRoundedUp();
+
+        /**
+         * Indicates whether the binary to ASCII conversion was exact.
+         *
+         * @return <code>true</code> if any only if the conversion was exact.
+         */
+        public boolean decimalDigitsExact();
+    }
+
+    /**
+     * A <code>BinaryToASCIIConverter</code> which represents <code>NaN</code>
+     * and infinite values.
+     */
+    private static class ExceptionalBinaryToASCIIBuffer implements BinaryToASCIIConverter {
+        private final String image;
+        private boolean isNegative;
+
+        public ExceptionalBinaryToASCIIBuffer(String image, boolean isNegative) {
+            this.image = image;
+            this.isNegative = isNegative;
+        }
+
+        @Override
+        public String toJavaFormatString() {
+            return image;
+        }
+
+        @Override
+        public void appendTo(Appendable buf) {
+            if (buf instanceof StringBuilder) {
+                ((StringBuilder) buf).append(image);
+            } else if (buf instanceof StringBuffer) {
+                ((StringBuffer) buf).append(image);
+            } else {
+                assert false;
+            }
+        }
+
+        @Override
+        public int getDecimalExponent() {
+            throw new IllegalArgumentException("Exceptional value does not have an exponent");
+        }
+
+        @Override
+        public int getDigits(char[] digits) {
+            throw new IllegalArgumentException("Exceptional value does not have digits");
+        }
+
+        @Override
+        public boolean isNegative() {
+            return isNegative;
+        }
+
+        @Override
+        public boolean isExceptional() {
+            return true;
+        }
+
+        @Override
+        public boolean digitsRoundedUp() {
+            throw new IllegalArgumentException("Exceptional value is not rounded");
+        }
+
+        @Override
+        public boolean decimalDigitsExact() {
+            throw new IllegalArgumentException("Exceptional value is not exact");
+        }
+    }
+
+    private static final String INFINITY_REP = "Infinity";
+    private static final int INFINITY_LENGTH = INFINITY_REP.length();
+    private static final String NAN_REP = "NaN";
+    private static final int NAN_LENGTH = NAN_REP.length();
+
+    private static final BinaryToASCIIConverter B2AC_POSITIVE_INFINITY = new ExceptionalBinaryToASCIIBuffer(INFINITY_REP, false);
+    private static final BinaryToASCIIConverter B2AC_NEGATIVE_INFINITY = new ExceptionalBinaryToASCIIBuffer("-" + INFINITY_REP, true);
+    private static final BinaryToASCIIConverter B2AC_NOT_A_NUMBER = new ExceptionalBinaryToASCIIBuffer(NAN_REP, false);
+    private static final BinaryToASCIIConverter B2AC_POSITIVE_ZERO = new BinaryToASCIIBuffer(false, new char[]{'0'});
+    private static final BinaryToASCIIConverter B2AC_NEGATIVE_ZERO = new BinaryToASCIIBuffer(true,  new char[]{'0'});
+
+    /**
+     * A buffered implementation of <code>BinaryToASCIIConverter</code>.
+     */
+    static class BinaryToASCIIBuffer implements BinaryToASCIIConverter {
+        private boolean isNegative;
+        private int decExponent;
+        private int firstDigitIndex;
+        private int nDigits;
+        private final char[] digits;
+        private final char[] buffer = new char[26];
+
+        //
+        // The fields below provide additional information about the result of
+        // the binary to decimal digits conversion done in dtoa() and roundup()
+        // methods. They are changed if needed by those two methods.
+        //
+
+        // True if the dtoa() binary to decimal conversion was exact.
+        private boolean exactDecimalConversion = false;
+
+        // True if the result of the binary to decimal conversion was rounded-up
+        // at the end of the conversion process, i.e. roundUp() method was called.
+        private boolean decimalDigitsRoundedUp = false;
+
+        /**
+         * Default constructor; used for non-zero values,
+         * <code>BinaryToASCIIBuffer</code> may be thread-local and reused
+         */
+        BinaryToASCIIBuffer(){
+            this.digits = new char[20];
+        }
+
+        /**
+         * Creates a specialized value (positive and negative zeros).
+         */
+        BinaryToASCIIBuffer(boolean isNegative, char[] digits){
+            this.isNegative = isNegative;
+            this.decExponent  = 0;
+            this.digits = digits;
+            this.firstDigitIndex = 0;
+            this.nDigits = digits.length;
+        }
+
+        @Override
+        public String toJavaFormatString() {
+            int len = getChars(buffer);
+            return new String(buffer, 0, len);
+        }
+
+        @Override
+        public void appendTo(Appendable buf) {
+            int len = getChars(buffer);
+            if (buf instanceof StringBuilder) {
+                ((StringBuilder) buf).append(buffer, 0, len);
+            } else if (buf instanceof StringBuffer) {
+                ((StringBuffer) buf).append(buffer, 0, len);
+            } else {
+                assert false;
+            }
+        }
+
+        @Override
+        public int getDecimalExponent() {
+            return decExponent;
+        }
+
+        @Override
+        public int getDigits(char[] digits) {
+            System.arraycopy(this.digits,firstDigitIndex,digits,0,this.nDigits);
+            return this.nDigits;
+        }
+
+        @Override
+        public boolean isNegative() {
+            return isNegative;
+        }
+
+        @Override
+        public boolean isExceptional() {
+            return false;
+        }
+
+        @Override
+        public boolean digitsRoundedUp() {
+            return decimalDigitsRoundedUp;
+        }
+
+        @Override
+        public boolean decimalDigitsExact() {
+            return exactDecimalConversion;
+        }
+
+        private void setSign(boolean isNegative) {
+            this.isNegative = isNegative;
+        }
+
+        /**
+         * This is the easy subcase --
+         * all the significant bits, after scaling, are held in lvalue.
+         * negSign and decExponent tell us what processing and scaling
+         * has already been done. Exceptional cases have already been
+         * stripped out.
+         * In particular:
+         * lvalue is a finite number (not Inf, nor NaN)
+         * lvalue > 0L (not zero, nor negative).
+         *
+         * The only reason that we develop the digits here, rather than
+         * calling on Long.toString() is that we can do it a little faster,
+         * and besides want to treat trailing 0s specially. If Long.toString
+         * changes, we should re-evaluate this strategy!
+         */
+        private void developLongDigits( int decExponent, long lvalue, int insignificantDigits ){
+            if ( insignificantDigits != 0 ){
+                // Discard non-significant low-order bits, while rounding,
+                // up to insignificant value.
+                long pow10 = FDBigInteger.LONG_5_POW[insignificantDigits] << insignificantDigits; // 10^i == 5^i * 2^i;
+                long residue = lvalue % pow10;
+                lvalue /= pow10;
+                decExponent += insignificantDigits;
+                if ( residue >= (pow10>>1) ){
+                    // round up based on the low-order bits we're discarding
+                    lvalue++;
+                }
+            }
+            int  digitno = digits.length -1;
+            int  c;
+            if ( lvalue <= Integer.MAX_VALUE ){
+                assert lvalue > 0L : lvalue; // lvalue <= 0
+                // even easier subcase!
+                // can do int arithmetic rather than long!
+                int  ivalue = (int)lvalue;
+                c = ivalue%10;
+                ivalue /= 10;
+                while ( c == 0 ){
+                    decExponent++;
+                    c = ivalue%10;
+                    ivalue /= 10;
+                }
+                while ( ivalue != 0){
+                    digits[digitno--] = (char)(c+'0');
+                    decExponent++;
+                    c = ivalue%10;
+                    ivalue /= 10;
+                }
+                digits[digitno] = (char)(c+'0');
+            } else {
+                // same algorithm as above (same bugs, too )
+                // but using long arithmetic.
+                c = (int)(lvalue%10L);
+                lvalue /= 10L;
+                while ( c == 0 ){
+                    decExponent++;
+                    c = (int)(lvalue%10L);
+                    lvalue /= 10L;
+                }
+                while ( lvalue != 0L ){
+                    digits[digitno--] = (char)(c+'0');
+                    decExponent++;
+                    c = (int)(lvalue%10L);
+                    lvalue /= 10;
+                }
+                digits[digitno] = (char)(c+'0');
+            }
+            this.decExponent = decExponent+1;
+            this.firstDigitIndex = digitno;
+            this.nDigits = this.digits.length - digitno;
+        }
+
+        private void dtoa( int binExp, long fractBits, int nSignificantBits, boolean isCompatibleFormat)
+        {
+            assert fractBits > 0 ; // fractBits here can't be zero or negative
+            assert (fractBits & FRACT_HOB)!=0  ; // Hi-order bit should be set
+            // Examine number. Determine if it is an easy case,
+            // which we can do pretty trivially using float/long conversion,
+            // or whether we must do real work.
+            final int tailZeros = Long.numberOfTrailingZeros(fractBits);
+
+            // number of significant bits of fractBits;
+            final int nFractBits = EXP_SHIFT+1-tailZeros;
+
+            // reset flags to default values as dtoa() does not always set these
+            // flags and a prior call to dtoa() might have set them to incorrect
+            // values with respect to the current state.
+            decimalDigitsRoundedUp = false;
+            exactDecimalConversion = false;
+
+            // number of significant bits to the right of the point.
+            int nTinyBits = Math.max( 0, nFractBits - binExp - 1 );
+            if ( binExp <= MAX_SMALL_BIN_EXP && binExp >= MIN_SMALL_BIN_EXP ){
+                // Look more closely at the number to decide if,
+                // with scaling by 10^nTinyBits, the result will fit in
+                // a long.
+                if ( (nTinyBits < FDBigInteger.LONG_5_POW.length) && ((nFractBits + N_5_BITS[nTinyBits]) < 64 ) ){
+                    //
+                    // We can do this:
+                    // take the fraction bits, which are normalized.
+                    // (a) nTinyBits == 0: Shift left or right appropriately
+                    //     to align the binary point at the extreme right, i.e.
+                    //     where a long int point is expected to be. The integer
+                    //     result is easily converted to a string.
+                    // (b) nTinyBits > 0: Shift right by EXP_SHIFT-nFractBits,
+                    //     which effectively converts to long and scales by
+                    //     2^nTinyBits. Then multiply by 5^nTinyBits to
+                    //     complete the scaling. We know this won't overflow
+                    //     because we just counted the number of bits necessary
+                    //     in the result. The integer you get from this can
+                    //     then be converted to a string pretty easily.
+                    //
+                    if ( nTinyBits == 0 ) {
+                        int insignificant;
+                        if ( binExp > nSignificantBits ){
+                            insignificant = insignificantDigitsForPow2(binExp-nSignificantBits-1);
+                        } else {
+                            insignificant = 0;
+                        }
+                        if ( binExp >= EXP_SHIFT ){
+                            fractBits <<= (binExp-EXP_SHIFT);
+                        } else {
+                            fractBits >>>= (EXP_SHIFT-binExp) ;
+                        }
+                        developLongDigits( 0, fractBits, insignificant );
+                        return;
+                    }
+                    //
+                    // The following causes excess digits to be printed
+                    // out in the single-float case. Our manipulation of
+                    // halfULP here is apparently not correct. If we
+                    // better understand how this works, perhaps we can
+                    // use this special case again. But for the time being,
+                    // we do not.
+                    // else {
+                    //     fractBits >>>= EXP_SHIFT+1-nFractBits;
+                    //     fractBits//= long5pow[ nTinyBits ];
+                    //     halfULP = long5pow[ nTinyBits ] >> (1+nSignificantBits-nFractBits);
+                    //     developLongDigits( -nTinyBits, fractBits, insignificantDigits(halfULP) );
+                    //     return;
+                    // }
+                    //
+                }
+            }
+            //
+            // This is the hard case. We are going to compute large positive
+            // integers B and S and integer decExp, s.t.
+            //      d = ( B / S )// 10^decExp
+            //      1 <= B / S < 10
+            // Obvious choices are:
+            //      decExp = floor( log10(d) )
+            //      B      = d// 2^nTinyBits// 10^max( 0, -decExp )
+            //      S      = 10^max( 0, decExp)// 2^nTinyBits
+            // (noting that nTinyBits has already been forced to non-negative)
+            // I am also going to compute a large positive integer
+            //      M      = (1/2^nSignificantBits)// 2^nTinyBits// 10^max( 0, -decExp )
+            // i.e. M is (1/2) of the ULP of d, scaled like B.
+            // When we iterate through dividing B/S and picking off the
+            // quotient bits, we will know when to stop when the remainder
+            // is <= M.
+            //
+            // We keep track of powers of 2 and powers of 5.
+            //
+            int decExp = estimateDecExp(fractBits,binExp);
+            int B2, B5; // powers of 2 and powers of 5, respectively, in B
+            int S2, S5; // powers of 2 and powers of 5, respectively, in S
+            int M2, M5; // powers of 2 and powers of 5, respectively, in M
+
+            B5 = Math.max( 0, -decExp );
+            B2 = B5 + nTinyBits + binExp;
+
+            S5 = Math.max( 0, decExp );
+            S2 = S5 + nTinyBits;
+
+            M5 = B5;
+            M2 = B2 - nSignificantBits;
+
+            //
+            // the long integer fractBits contains the (nFractBits) interesting
+            // bits from the mantissa of d ( hidden 1 added if necessary) followed
+            // by (EXP_SHIFT+1-nFractBits) zeros. In the interest of compactness,
+            // I will shift out those zeros before turning fractBits into a
+            // FDBigInteger. The resulting whole number will be
+            //      d * 2^(nFractBits-1-binExp).
+            //
+            fractBits >>>= tailZeros;
+            B2 -= nFractBits-1;
+            int common2factor = Math.min( B2, S2 );
+            B2 -= common2factor;
+            S2 -= common2factor;
+            M2 -= common2factor;
+
+            //
+            // HACK!! For exact powers of two, the next smallest number
+            // is only half as far away as we think (because the meaning of
+            // ULP changes at power-of-two bounds) for this reason, we
+            // hack M2. Hope this works.
+            //
+            if ( nFractBits == 1 ) {
+                M2 -= 1;
+            }
+
+            if ( M2 < 0 ){
+                // oops.
+                // since we cannot scale M down far enough,
+                // we must scale the other values up.
+                B2 -= M2;
+                S2 -= M2;
+                M2 =  0;
+            }
+            //
+            // Construct, Scale, iterate.
+            // Some day, we'll write a stopping test that takes
+            // account of the asymmetry of the spacing of floating-point
+            // numbers below perfect powers of 2
+            // 26 Sept 96 is not that day.
+            // So we use a symmetric test.
+            //
+            int ndigit = 0;
+            boolean low, high;
+            long lowDigitDifference;
+            int  q;
+
+            //
+            // Detect the special cases where all the numbers we are about
+            // to compute will fit in int or long integers.
+            // In these cases, we will avoid doing FDBigInteger arithmetic.
+            // We use the same algorithms, except that we "normalize"
+            // our FDBigIntegers before iterating. This is to make division easier,
+            // as it makes our fist guess (quotient of high-order words)
+            // more accurate!
+            //
+            // Some day, we'll write a stopping test that takes
+            // account of the asymmetry of the spacing of floating-point
+            // numbers below perfect powers of 2
+            // 26 Sept 96 is not that day.
+            // So we use a symmetric test.
+            //
+            // binary digits needed to represent B, approx.
+            int Bbits = nFractBits + B2 + (( B5 < N_5_BITS.length )? N_5_BITS[B5] : ( B5*3 ));
+
+            // binary digits needed to represent 10*S, approx.
+            int tenSbits = S2+1 + (( (S5+1) < N_5_BITS.length )? N_5_BITS[(S5+1)] : ( (S5+1)*3 ));
+            if ( Bbits < 64 && tenSbits < 64){
+                if ( Bbits < 32 && tenSbits < 32){
+                    // wa-hoo! They're all ints!
+                    int b = ((int)fractBits * FDBigInteger.SMALL_5_POW[B5] ) << B2;
+                    int s = FDBigInteger.SMALL_5_POW[S5] << S2;
+                    int m = FDBigInteger.SMALL_5_POW[M5] << M2;
+                    int tens = s * 10;
+                    //
+                    // Unroll the first iteration. If our decExp estimate
+                    // was too high, our first quotient will be zero. In this
+                    // case, we discard it and decrement decExp.
+                    //
+                    ndigit = 0;
+                    q = b / s;
+                    b = 10 * ( b % s );
+                    m *= 10;
+                    low  = (b <  m );
+                    high = (b+m > tens );
+                    assert q < 10 : q; // excessively large digit
+                    if ( (q == 0) && ! high ){
+                        // oops. Usually ignore leading zero.
+                        decExp--;
+                    } else {
+                        digits[ndigit++] = (char)('0' + q);
+                    }
+                    //
+                    // HACK! Java spec sez that we always have at least
+                    // one digit after the . in either F- or E-form output.
+                    // Thus we will need more than one digit if we're using
+                    // E-form
+                    //
+                    if ( !isCompatibleFormat ||decExp < -3 || decExp >= 8 ){
+                        high = low = false;
+                    }
+                    while( ! low && ! high ){
+                        q = b / s;
+                        b = 10 * ( b % s );
+                        m *= 10;
+                        assert q < 10 : q; // excessively large digit
+                        if ( m > 0L ){
+                            low  = (b <  m );
+                            high = (b+m > tens );
+                        } else {
+                            // hack -- m might overflow!
+                            // in this case, it is certainly > b,
+                            // which won't
+                            // and b+m > tens, too, since that has overflowed
+                            // either!
+                            low = true;
+                            high = true;
+                        }
+                        digits[ndigit++] = (char)('0' + q);
+                    }
+                    lowDigitDifference = (b<<1) - tens;
+                    exactDecimalConversion  = (b == 0);
+                } else {
+                    // still good! they're all longs!
+                    long b = (fractBits * FDBigInteger.LONG_5_POW[B5] ) << B2;
+                    long s = FDBigInteger.LONG_5_POW[S5] << S2;
+                    long m = FDBigInteger.LONG_5_POW[M5] << M2;
+                    long tens = s * 10L;
+                    //
+                    // Unroll the first iteration. If our decExp estimate
+                    // was too high, our first quotient will be zero. In this
+                    // case, we discard it and decrement decExp.
+                    //
+                    ndigit = 0;
+                    q = (int) ( b / s );
+                    b = 10L * ( b % s );
+                    m *= 10L;
+                    low  = (b <  m );
+                    high = (b+m > tens );
+                    assert q < 10 : q; // excessively large digit
+                    if ( (q == 0) && ! high ){
+                        // oops. Usually ignore leading zero.
+                        decExp--;
+                    } else {
+                        digits[ndigit++] = (char)('0' + q);
+                    }
+                    //
+                    // HACK! Java spec sez that we always have at least
+                    // one digit after the . in either F- or E-form output.
+                    // Thus we will need more than one digit if we're using
+                    // E-form
+                    //
+                    if ( !isCompatibleFormat || decExp < -3 || decExp >= 8 ){
+                        high = low = false;
+                    }
+                    while( ! low && ! high ){
+                        q = (int) ( b / s );
+                        b = 10 * ( b % s );
+                        m *= 10;
+                        assert q < 10 : q;  // excessively large digit
+                        if ( m > 0L ){
+                            low  = (b <  m );
+                            high = (b+m > tens );
+                        } else {
+                            // hack -- m might overflow!
+                            // in this case, it is certainly > b,
+                            // which won't
+                            // and b+m > tens, too, since that has overflowed
+                            // either!
+                            low = true;
+                            high = true;
+                        }
+                        digits[ndigit++] = (char)('0' + q);
+                    }
+                    lowDigitDifference = (b<<1) - tens;
+                    exactDecimalConversion  = (b == 0);
+                }
+            } else {
+                //
+                // We really must do FDBigInteger arithmetic.
+                // Fist, construct our FDBigInteger initial values.
+                //
+                FDBigInteger Sval = FDBigInteger.valueOfPow52(S5, S2);
+                int shiftBias = Sval.getNormalizationBias();
+                Sval = Sval.leftShift(shiftBias); // normalize so that division works better
+
+                FDBigInteger Bval = FDBigInteger.valueOfMulPow52(fractBits, B5, B2 + shiftBias);
+                FDBigInteger Mval = FDBigInteger.valueOfPow52(M5 + 1, M2 + shiftBias + 1);
+
+                FDBigInteger tenSval = FDBigInteger.valueOfPow52(S5 + 1, S2 + shiftBias + 1); //Sval.mult( 10 );
+                //
+                // Unroll the first iteration. If our decExp estimate
+                // was too high, our first quotient will be zero. In this
+                // case, we discard it and decrement decExp.
+                //
+                ndigit = 0;
+                q = Bval.quoRemIteration( Sval );
+                low  = (Bval.cmp( Mval ) < 0);
+                high = tenSval.addAndCmp(Bval,Mval)<=0;
+
+                assert q < 10 : q; // excessively large digit
+                if ( (q == 0) && ! high ){
+                    // oops. Usually ignore leading zero.
+                    decExp--;
+                } else {
+                    digits[ndigit++] = (char)('0' + q);
+                }
+                //
+                // HACK! Java spec sez that we always have at least
+                // one digit after the . in either F- or E-form output.
+                // Thus we will need more than one digit if we're using
+                // E-form
+                //
+                if (!isCompatibleFormat || decExp < -3 || decExp >= 8 ){
+                    high = low = false;
+                }
+                while( ! low && ! high ){
+                    q = Bval.quoRemIteration( Sval );
+                    assert q < 10 : q;  // excessively large digit
+                    Mval = Mval.multBy10(); //Mval = Mval.mult( 10 );
+                    low  = (Bval.cmp( Mval ) < 0);
+                    high = tenSval.addAndCmp(Bval,Mval)<=0;
+                    digits[ndigit++] = (char)('0' + q);
+                }
+                if ( high && low ){
+                    Bval = Bval.leftShift(1);
+                    lowDigitDifference = Bval.cmp(tenSval);
+                } else {
+                    lowDigitDifference = 0L; // this here only for flow analysis!
+                }
+                exactDecimalConversion  = (Bval.cmp( FDBigInteger.ZERO ) == 0);
+            }
+            this.decExponent = decExp+1;
+            this.firstDigitIndex = 0;
+            this.nDigits = ndigit;
+            //
+            // Last digit gets rounded based on stopping condition.
+            //
+            if ( high ){
+                if ( low ){
+                    if ( lowDigitDifference == 0L ){
+                        // it's a tie!
+                        // choose based on which digits we like.
+                        if ( (digits[firstDigitIndex+nDigits-1]&1) != 0 ) {
+                            roundup();
+                        }
+                    } else if ( lowDigitDifference > 0 ){
+                        roundup();
+                    }
+                } else {
+                    roundup();
+                }
+            }
+        }
+
+        // add one to the least significant digit.
+        // in the unlikely event there is a carry out, deal with it.
+        // assert that this will only happen where there
+        // is only one digit, e.g. (float)1e-44 seems to do it.
+        //
+        private void roundup() {
+            int i = (firstDigitIndex + nDigits - 1);
+            int q = digits[i];
+            if (q == '9') {
+                while (q == '9' && i > firstDigitIndex) {
+                    digits[i] = '0';
+                    q = digits[--i];
+                }
+                if (q == '9') {
+                    // carryout! High-order 1, rest 0s, larger exp.
+                    decExponent += 1;
+                    digits[firstDigitIndex] = '1';
+                    return;
+                }
+                // else fall through.
+            }
+            digits[i] = (char) (q + 1);
+            decimalDigitsRoundedUp = true;
+        }
+
+        /**
+         * Estimate decimal exponent. (If it is small-ish,
+         * we could double-check.)
+         *
+         * First, scale the mantissa bits such that 1 <= d2 < 2.
+         * We are then going to estimate
+         *          log10(d2) ~=~  (d2-1.5)/1.5 + log(1.5)
+         * and so we can estimate
+         *      log10(d) ~=~ log10(d2) + binExp * log10(2)
+         * take the floor and call it decExp.
+         */
+        static int estimateDecExp(long fractBits, int binExp) {
+            double d2 = Double.longBitsToDouble( EXP_ONE | ( fractBits & DoubleConsts.SIGNIF_BIT_MASK ) );
+            double d = (d2-1.5D)*0.289529654D + 0.176091259 + (double)binExp * 0.301029995663981;
+            long dBits = Double.doubleToRawLongBits(d);  //can't be NaN here so use raw
+            int exponent = (int)((dBits & DoubleConsts.EXP_BIT_MASK) >> EXP_SHIFT) - DoubleConsts.EXP_BIAS;
+            boolean isNegative = (dBits & DoubleConsts.SIGN_BIT_MASK) != 0; // discover sign
+            if(exponent>=0 && exponent<52) { // hot path
+                long mask   = DoubleConsts.SIGNIF_BIT_MASK >> exponent;
+                int r = (int)(( (dBits&DoubleConsts.SIGNIF_BIT_MASK) | FRACT_HOB )>>(EXP_SHIFT-exponent));
+                return isNegative ? (((mask & dBits) == 0L ) ? -r : -r-1 ) : r;
+            } else if (exponent < 0) {
+                return (((dBits&~DoubleConsts.SIGN_BIT_MASK) == 0) ? 0 :
+                        ( (isNegative) ? -1 : 0) );
+            } else { //if (exponent >= 52)
+                return (int)d;
+            }
+        }
+
+        private static int insignificantDigits(int insignificant) {
+            int i;
+            for ( i = 0; insignificant >= 10L; i++ ) {
+                insignificant /= 10L;
+            }
+            return i;
+        }
+
+        /**
+         * Calculates
+         * <pre>
+         * insignificantDigitsForPow2(v) == insignificantDigits(1L<<v)
+         * </pre>
+         */
+        private static int insignificantDigitsForPow2(int p2) {
+            if(p2>1 && p2 < insignificantDigitsNumber.length) {
+                return insignificantDigitsNumber[p2];
+            }
+            return 0;
+        }
+
+        /**
+         *  If insignificant==(1L << ixd)
+         *  i = insignificantDigitsNumber[idx] is the same as:
+         *  int i;
+         *  for ( i = 0; insignificant >= 10L; i++ )
+         *         insignificant /= 10L;
+         */
+        private static int[] insignificantDigitsNumber = {
+            0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3,
+            4, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7,
+            8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 11, 11, 11,
+            12, 12, 12, 12, 13, 13, 13, 14, 14, 14,
+            15, 15, 15, 15, 16, 16, 16, 17, 17, 17,
+            18, 18, 18, 19
+        };
+
+        // approximately ceil( log2( long5pow[i] ) )
+        private static final int[] N_5_BITS = {
+                0,
+                3,
+                5,
+                7,
+                10,
+                12,
+                14,
+                17,
+                19,
+                21,
+                24,
+                26,
+                28,
+                31,
+                33,
+                35,
+                38,
+                40,
+                42,
+                45,
+                47,
+                49,
+                52,
+                54,
+                56,
+                59,
+                61,
+        };
+
+        private int getChars(char[] result) {
+            assert nDigits <= 19 : nDigits; // generous bound on size of nDigits
+            int i = 0;
+            if (isNegative) {
+                result[0] = '-';
+                i = 1;
+            }
+            if (decExponent > 0 && decExponent < 8) {
+                // print digits.digits.
+                int charLength = Math.min(nDigits, decExponent);
+                System.arraycopy(digits, firstDigitIndex, result, i, charLength);
+                i += charLength;
+                if (charLength < decExponent) {
+                    charLength = decExponent - charLength;
+                    Arrays.fill(result,i,i+charLength,'0');
+                    i += charLength;
+                    result[i++] = '.';
+                    result[i++] = '0';
+                } else {
+                    result[i++] = '.';
+                    if (charLength < nDigits) {
+                        int t = nDigits - charLength;
+                        System.arraycopy(digits, firstDigitIndex+charLength, result, i, t);
+                        i += t;
+                    } else {
+                        result[i++] = '0';
+                    }
+                }
+            } else if (decExponent <= 0 && decExponent > -3) {
+                result[i++] = '0';
+                result[i++] = '.';
+                if (decExponent != 0) {
+                    Arrays.fill(result, i, i-decExponent, '0');
+                    i -= decExponent;
+                }
+                System.arraycopy(digits, firstDigitIndex, result, i, nDigits);
+                i += nDigits;
+            } else {
+                result[i++] = digits[firstDigitIndex];
+                result[i++] = '.';
+                if (nDigits > 1) {
+                    System.arraycopy(digits, firstDigitIndex+1, result, i, nDigits - 1);
+                    i += nDigits - 1;
+                } else {
+                    result[i++] = '0';
+                }
+                result[i++] = 'E';
+                int e;
+                if (decExponent <= 0) {
+                    result[i++] = '-';
+                    e = -decExponent + 1;
+                } else {
+                    e = decExponent - 1;
+                }
+                // decExponent has 1, 2, or 3, digits
+                if (e <= 9) {
+                    result[i++] = (char) (e + '0');
+                } else if (e <= 99) {
+                    result[i++] = (char) (e / 10 + '0');
+                    result[i++] = (char) (e % 10 + '0');
+                } else {
+                    result[i++] = (char) (e / 100 + '0');
+                    e %= 100;
+                    result[i++] = (char) (e / 10 + '0');
+                    result[i++] = (char) (e % 10 + '0');
+                }
+            }
+            return i;
+        }
+
+    }
+
+    private static final ThreadLocal<BinaryToASCIIBuffer> threadLocalBinaryToASCIIBuffer =
+            new ThreadLocal<BinaryToASCIIBuffer>() {
+                @Override
+                protected BinaryToASCIIBuffer initialValue() {
+                    return new BinaryToASCIIBuffer();
+                }
+            };
+
+    private static BinaryToASCIIBuffer getBinaryToASCIIBuffer() {
+        return threadLocalBinaryToASCIIBuffer.get();
+    }
+
+    /**
+     * A converter which can process an ASCII <code>String</code> representation
+     * of a single or double precision floating point value into a
+     * <code>float</code> or a <code>double</code>.
+     */
+    interface ASCIIToBinaryConverter {
+
+        double doubleValue();
+
+        float floatValue();
+
+    }
+
+    /**
+     * A <code>ASCIIToBinaryConverter</code> container for a <code>double</code>.
+     */
+    static class PreparedASCIIToBinaryBuffer implements ASCIIToBinaryConverter {
+        private final double doubleVal;
+        private final float floatVal;
+
+        public PreparedASCIIToBinaryBuffer(double doubleVal, float floatVal) {
+            this.doubleVal = doubleVal;
+            this.floatVal = floatVal;
+        }
+
+        @Override
+        public double doubleValue() {
+            return doubleVal;
+        }
+
+        @Override
+        public float floatValue() {
+            return floatVal;
+        }
+    }
+
+    static final ASCIIToBinaryConverter A2BC_POSITIVE_INFINITY = new PreparedASCIIToBinaryBuffer(Double.POSITIVE_INFINITY, Float.POSITIVE_INFINITY);
+    static final ASCIIToBinaryConverter A2BC_NEGATIVE_INFINITY = new PreparedASCIIToBinaryBuffer(Double.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY);
+    static final ASCIIToBinaryConverter A2BC_NOT_A_NUMBER  = new PreparedASCIIToBinaryBuffer(Double.NaN, Float.NaN);
+    static final ASCIIToBinaryConverter A2BC_POSITIVE_ZERO = new PreparedASCIIToBinaryBuffer(0.0d, 0.0f);
+    static final ASCIIToBinaryConverter A2BC_NEGATIVE_ZERO = new PreparedASCIIToBinaryBuffer(-0.0d, -0.0f);
+
+    /**
+     * A buffered implementation of <code>ASCIIToBinaryConverter</code>.
+     */
+    static class ASCIIToBinaryBuffer implements ASCIIToBinaryConverter {
+        boolean     isNegative;
+        int         decExponent;
+        char        digits[];
+        int         nDigits;
+
+        ASCIIToBinaryBuffer( boolean negSign, int decExponent, char[] digits, int n)
+        {
+            this.isNegative = negSign;
+            this.decExponent = decExponent;
+            this.digits = digits;
+            this.nDigits = n;
+        }
+
+        /**
+         * Takes a FloatingDecimal, which we presumably just scanned in,
+         * and finds out what its value is, as a double.
+         *
+         * AS A SIDE EFFECT, SET roundDir TO INDICATE PREFERRED
+         * ROUNDING DIRECTION in case the result is really destined
+         * for a single-precision float.
+         */
+        @Override
+        public double doubleValue() {
+            int kDigits = Math.min(nDigits, MAX_DECIMAL_DIGITS + 1);
+            //
+            // convert the lead kDigits to a long integer.
+            //
+            // (special performance hack: start to do it using int)
+            int iValue = (int) digits[0] - (int) '0';
+            int iDigits = Math.min(kDigits, INT_DECIMAL_DIGITS);
+            for (int i = 1; i < iDigits; i++) {
+                iValue = iValue * 10 + (int) digits[i] - (int) '0';
+            }
+            long lValue = (long) iValue;
+            for (int i = iDigits; i < kDigits; i++) {
+                lValue = lValue * 10L + (long) ((int) digits[i] - (int) '0');
+            }
+            double dValue = (double) lValue;
+            int exp = decExponent - kDigits;
+            //
+            // lValue now contains a long integer with the value of
+            // the first kDigits digits of the number.
+            // dValue contains the (double) of the same.
+            //
+
+            if (nDigits <= MAX_DECIMAL_DIGITS) {
+                //
+                // possibly an easy case.
+                // We know that the digits can be represented
+                // exactly. And if the exponent isn't too outrageous,
+                // the whole thing can be done with one operation,
+                // thus one rounding error.
+                // Note that all our constructors trim all leading and
+                // trailing zeros, so simple values (including zero)
+                // will always end up here
+                //
+                if (exp == 0 || dValue == 0.0) {
+                    return (isNegative) ? -dValue : dValue; // small floating integer
+                }
+                else if (exp >= 0) {
+                    if (exp <= MAX_SMALL_TEN) {
+                        //
+                        // Can get the answer with one operation,
+                        // thus one roundoff.
+                        //
+                        double rValue = dValue * SMALL_10_POW[exp];
+                        return (isNegative) ? -rValue : rValue;
+                    }
+                    int slop = MAX_DECIMAL_DIGITS - kDigits;
+                    if (exp <= MAX_SMALL_TEN + slop) {
+                        //
+                        // We can multiply dValue by 10^(slop)
+                        // and it is still "small" and exact.
+                        // Then we can multiply by 10^(exp-slop)
+                        // with one rounding.
+                        //
+                        dValue *= SMALL_10_POW[slop];
+                        double rValue = dValue * SMALL_10_POW[exp - slop];
+                        return (isNegative) ? -rValue : rValue;
+                    }
+                    //
+                    // Else we have a hard case with a positive exp.
+                    //
+                } else {
+                    if (exp >= -MAX_SMALL_TEN) {
+                        //
+                        // Can get the answer in one division.
+                        //
+                        double rValue = dValue / SMALL_10_POW[-exp];
+                        return (isNegative) ? -rValue : rValue;
+                    }
+                    //
+                    // Else we have a hard case with a negative exp.
+                    //
+                }
+            }
+
+            //
+            // Harder cases:
+            // The sum of digits plus exponent is greater than
+            // what we think we can do with one error.
+            //
+            // Start by approximating the right answer by,
+            // naively, scaling by powers of 10.
+            //
+            if (exp > 0) {
+                if (decExponent > MAX_DECIMAL_EXPONENT + 1) {
+                    //
+                    // Lets face it. This is going to be
+                    // Infinity. Cut to the chase.
+                    //
+                    return (isNegative) ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
+                }
+                if ((exp & 15) != 0) {
+                    dValue *= SMALL_10_POW[exp & 15];
+                }
+                if ((exp >>= 4) != 0) {
+                    int j;
+                    for (j = 0; exp > 1; j++, exp >>= 1) {
+                        if ((exp & 1) != 0) {
+                            dValue *= BIG_10_POW[j];
+                        }
+                    }
+                    //
+                    // The reason for the weird exp > 1 condition
+                    // in the above loop was so that the last multiply
+                    // would get unrolled. We handle it here.
+                    // It could overflow.
+                    //
+                    double t = dValue * BIG_10_POW[j];
+                    if (Double.isInfinite(t)) {
+                        //
+                        // It did overflow.
+                        // Look more closely at the result.
+                        // If the exponent is just one too large,
+                        // then use the maximum finite as our estimate
+                        // value. Else call the result infinity
+                        // and punt it.
+                        // ( I presume this could happen because
+                        // rounding forces the result here to be
+                        // an ULP or two larger than
+                        // Double.MAX_VALUE ).
+                        //
+                        t = dValue / 2.0;
+                        t *= BIG_10_POW[j];
+                        if (Double.isInfinite(t)) {
+                            return (isNegative) ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
+                        }
+                        t = Double.MAX_VALUE;
+                    }
+                    dValue = t;
+                }
+            } else if (exp < 0) {
+                exp = -exp;
+                if (decExponent < MIN_DECIMAL_EXPONENT - 1) {
+                    //
+                    // Lets face it. This is going to be
+                    // zero. Cut to the chase.
+                    //
+                    return (isNegative) ? -0.0 : 0.0;
+                }
+                if ((exp & 15) != 0) {
+                    dValue /= SMALL_10_POW[exp & 15];
+                }
+                if ((exp >>= 4) != 0) {
+                    int j;
+                    for (j = 0; exp > 1; j++, exp >>= 1) {
+                        if ((exp & 1) != 0) {
+                            dValue *= TINY_10_POW[j];
+                        }
+                    }
+                    //
+                    // The reason for the weird exp > 1 condition
+                    // in the above loop was so that the last multiply
+                    // would get unrolled. We handle it here.
+                    // It could underflow.
+                    //
+                    double t = dValue * TINY_10_POW[j];
+                    if (t == 0.0) {
+                        //
+                        // It did underflow.
+                        // Look more closely at the result.
+                        // If the exponent is just one too small,
+                        // then use the minimum finite as our estimate
+                        // value. Else call the result 0.0
+                        // and punt it.
+                        // ( I presume this could happen because
+                        // rounding forces the result here to be
+                        // an ULP or two less than
+                        // Double.MIN_VALUE ).
+                        //
+                        t = dValue * 2.0;
+                        t *= TINY_10_POW[j];
+                        if (t == 0.0) {
+                            return (isNegative) ? -0.0 : 0.0;
+                        }
+                        t = Double.MIN_VALUE;
+                    }
+                    dValue = t;
+                }
+            }
+
+            //
+            // dValue is now approximately the result.
+            // The hard part is adjusting it, by comparison
+            // with FDBigInteger arithmetic.
+            // Formulate the EXACT big-number result as
+            // bigD0 * 10^exp
+            //
+            if (nDigits > MAX_NDIGITS) {
+                nDigits = MAX_NDIGITS + 1;
+                digits[MAX_NDIGITS] = '1';
+            }
+            FDBigInteger bigD0 = new FDBigInteger(lValue, digits, kDigits, nDigits);
+            exp = decExponent - nDigits;
+
+            long ieeeBits = Double.doubleToRawLongBits(dValue); // IEEE-754 bits of double candidate
+            final int B5 = Math.max(0, -exp); // powers of 5 in bigB, value is not modified inside correctionLoop
+            final int D5 = Math.max(0, exp); // powers of 5 in bigD, value is not modified inside correctionLoop
+            bigD0 = bigD0.multByPow52(D5, 0);
+            bigD0.makeImmutable();   // prevent bigD0 modification inside correctionLoop
+            FDBigInteger bigD = null;
+            int prevD2 = 0;
+
+            correctionLoop:
+            while (true) {
+                // here ieeeBits can't be NaN, Infinity or zero
+                int binexp = (int) (ieeeBits >>> EXP_SHIFT);
+                long bigBbits = ieeeBits & DoubleConsts.SIGNIF_BIT_MASK;
+                if (binexp > 0) {
+                    bigBbits |= FRACT_HOB;
+                } else { // Normalize denormalized numbers.
+                    assert bigBbits != 0L : bigBbits; // doubleToBigInt(0.0)
+                    int leadingZeros = Long.numberOfLeadingZeros(bigBbits);
+                    int shift = leadingZeros - (63 - EXP_SHIFT);
+                    bigBbits <<= shift;
+                    binexp = 1 - shift;
+                }
+                binexp -= DoubleConsts.EXP_BIAS;
+                int lowOrderZeros = Long.numberOfTrailingZeros(bigBbits);
+                bigBbits >>>= lowOrderZeros;
+                final int bigIntExp = binexp - EXP_SHIFT + lowOrderZeros;
+                final int bigIntNBits = EXP_SHIFT + 1 - lowOrderZeros;
+
+                //
+                // Scale bigD, bigB appropriately for
+                // big-integer operations.
+                // Naively, we multiply by powers of ten
+                // and powers of two. What we actually do
+                // is keep track of the powers of 5 and
+                // powers of 2 we would use, then factor out
+                // common divisors before doing the work.
+                //
+                int B2 = B5; // powers of 2 in bigB
+                int D2 = D5; // powers of 2 in bigD
+                int Ulp2;   // powers of 2 in halfUlp.
+                if (bigIntExp >= 0) {
+                    B2 += bigIntExp;
+                } else {
+                    D2 -= bigIntExp;
+                }
+                Ulp2 = B2;
+                // shift bigB and bigD left by a number s. t.
+                // halfUlp is still an integer.
+                int hulpbias;
+                if (binexp <= -DoubleConsts.EXP_BIAS) {
+                    // This is going to be a denormalized number
+                    // (if not actually zero).
+                    // half an ULP is at 2^-(DoubleConsts.EXP_BIAS+EXP_SHIFT+1)
+                    hulpbias = binexp + lowOrderZeros + DoubleConsts.EXP_BIAS;
+                } else {
+                    hulpbias = 1 + lowOrderZeros;
+                }
+                B2 += hulpbias;
+                D2 += hulpbias;
+                // if there are common factors of 2, we might just as well
+                // factor them out, as they add nothing useful.
+                int common2 = Math.min(B2, Math.min(D2, Ulp2));
+                B2 -= common2;
+                D2 -= common2;
+                Ulp2 -= common2;
+                // do multiplications by powers of 5 and 2
+                FDBigInteger bigB = FDBigInteger.valueOfMulPow52(bigBbits, B5, B2);
+                if (bigD == null || prevD2 != D2) {
+                    bigD = bigD0.leftShift(D2);
+                    prevD2 = D2;
+                }
+                //
+                // to recap:
+                // bigB is the scaled-big-int version of our floating-point
+                // candidate.
+                // bigD is the scaled-big-int version of the exact value
+                // as we understand it.
+                // halfUlp is 1/2 an ulp of bigB, except for special cases
+                // of exact powers of 2
+                //
+                // the plan is to compare bigB with bigD, and if the difference
+                // is less than halfUlp, then we're satisfied. Otherwise,
+                // use the ratio of difference to halfUlp to calculate a fudge
+                // factor to add to the floating value, then go 'round again.
+                //
+                FDBigInteger diff;
+                int cmpResult;
+                boolean overvalue;
+                if ((cmpResult = bigB.cmp(bigD)) > 0) {
+                    overvalue = true; // our candidate is too big.
+                    diff = bigB.leftInplaceSub(bigD); // bigB is not user further - reuse
+                    if ((bigIntNBits == 1) && (bigIntExp > -DoubleConsts.EXP_BIAS + 1)) {
+                        // candidate is a normalized exact power of 2 and
+                        // is too big (larger than Double.MIN_NORMAL). We will be subtracting.
+                        // For our purposes, ulp is the ulp of the
+                        // next smaller range.
+                        Ulp2 -= 1;
+                        if (Ulp2 < 0) {
+                            // rats. Cannot de-scale ulp this far.
+                            // must scale diff in other direction.
+                            Ulp2 = 0;
+                            diff = diff.leftShift(1);
+                        }
+                    }
+                } else if (cmpResult < 0) {
+                    overvalue = false; // our candidate is too small.
+                    diff = bigD.rightInplaceSub(bigB); // bigB is not user further - reuse
+                } else {
+                    // the candidate is exactly right!
+                    // this happens with surprising frequency
+                    break correctionLoop;
+                }
+                cmpResult = diff.cmpPow52(B5, Ulp2);
+                if ((cmpResult) < 0) {
+                    // difference is small.
+                    // this is close enough
+                    break correctionLoop;
+                } else if (cmpResult == 0) {
+                    // difference is exactly half an ULP
+                    // round to some other value maybe, then finish
+                    if ((ieeeBits & 1) != 0) { // half ties to even
+                        ieeeBits += overvalue ? -1 : 1; // nextDown or nextUp
+                    }
+                    break correctionLoop;
+                } else {
+                    // difference is non-trivial.
+                    // could scale addend by ratio of difference to
+                    // halfUlp here, if we bothered to compute that difference.
+                    // Most of the time ( I hope ) it is about 1 anyway.
+                    ieeeBits += overvalue ? -1 : 1; // nextDown or nextUp
+                    if (ieeeBits == 0 || ieeeBits == DoubleConsts.EXP_BIT_MASK) { // 0.0 or Double.POSITIVE_INFINITY
+                        break correctionLoop; // oops. Fell off end of range.
+                    }
+                    continue; // try again.
+                }
+
+            }
+            if (isNegative) {
+                ieeeBits |= DoubleConsts.SIGN_BIT_MASK;
+            }
+            return Double.longBitsToDouble(ieeeBits);
+        }
+
+        /**
+         * Takes a FloatingDecimal, which we presumably just scanned in,
+         * and finds out what its value is, as a float.
+         * This is distinct from doubleValue() to avoid the extremely
+         * unlikely case of a double rounding error, wherein the conversion
+         * to double has one rounding error, and the conversion of that double
+         * to a float has another rounding error, IN THE WRONG DIRECTION,
+         * ( because of the preference to a zero low-order bit ).
+         */
+        @Override
+        public float floatValue() {
+            int kDigits = Math.min(nDigits, SINGLE_MAX_DECIMAL_DIGITS + 1);
+            //
+            // convert the lead kDigits to an integer.
+            //
+            int iValue = (int) digits[0] - (int) '0';
+            for (int i = 1; i < kDigits; i++) {
+                iValue = iValue * 10 + (int) digits[i] - (int) '0';
+            }
+            float fValue = (float) iValue;
+            int exp = decExponent - kDigits;
+            //
+            // iValue now contains an integer with the value of
+            // the first kDigits digits of the number.
+            // fValue contains the (float) of the same.
+            //
+
+            if (nDigits <= SINGLE_MAX_DECIMAL_DIGITS) {
+                //
+                // possibly an easy case.
+                // We know that the digits can be represented
+                // exactly. And if the exponent isn't too outrageous,
+                // the whole thing can be done with one operation,
+                // thus one rounding error.
+                // Note that all our constructors trim all leading and
+                // trailing zeros, so simple values (including zero)
+                // will always end up here.
+                //
+                if (exp == 0 || fValue == 0.0f) {
+                    return (isNegative) ? -fValue : fValue; // small floating integer
+                } else if (exp >= 0) {
+                    if (exp <= SINGLE_MAX_SMALL_TEN) {
+                        //
+                        // Can get the answer with one operation,
+                        // thus one roundoff.
+                        //
+                        fValue *= SINGLE_SMALL_10_POW[exp];
+                        return (isNegative) ? -fValue : fValue;
+                    }
+                    int slop = SINGLE_MAX_DECIMAL_DIGITS - kDigits;
+                    if (exp <= SINGLE_MAX_SMALL_TEN + slop) {
+                        //
+                        // We can multiply fValue by 10^(slop)
+                        // and it is still "small" and exact.
+                        // Then we can multiply by 10^(exp-slop)
+                        // with one rounding.
+                        //
+                        fValue *= SINGLE_SMALL_10_POW[slop];
+                        fValue *= SINGLE_SMALL_10_POW[exp - slop];
+                        return (isNegative) ? -fValue : fValue;
+                    }
+                    //
+                    // Else we have a hard case with a positive exp.
+                    //
+                } else {
+                    if (exp >= -SINGLE_MAX_SMALL_TEN) {
+                        //
+                        // Can get the answer in one division.
+                        //
+                        fValue /= SINGLE_SMALL_10_POW[-exp];
+                        return (isNegative) ? -fValue : fValue;
+                    }
+                    //
+                    // Else we have a hard case with a negative exp.
+                    //
+                }
+            } else if ((decExponent >= nDigits) && (nDigits + decExponent <= MAX_DECIMAL_DIGITS)) {
+                //
+                // In double-precision, this is an exact floating integer.
+                // So we can compute to double, then shorten to float
+                // with one round, and get the right answer.
+                //
+                // First, finish accumulating digits.
+                // Then convert that integer to a double, multiply
+                // by the appropriate power of ten, and convert to float.
+                //
+                long lValue = (long) iValue;
+                for (int i = kDigits; i < nDigits; i++) {
+                    lValue = lValue * 10L + (long) ((int) digits[i] - (int) '0');
+                }
+                double dValue = (double) lValue;
+                exp = decExponent - nDigits;
+                dValue *= SMALL_10_POW[exp];
+                fValue = (float) dValue;
+                return (isNegative) ? -fValue : fValue;
+
+            }
+            //
+            // Harder cases:
+            // The sum of digits plus exponent is greater than
+            // what we think we can do with one error.
+            //
+            // Start by approximating the right answer by,
+            // naively, scaling by powers of 10.
+            // Scaling uses doubles to avoid overflow/underflow.
+            //
+            double dValue = fValue;
+            if (exp > 0) {
+                if (decExponent > SINGLE_MAX_DECIMAL_EXPONENT + 1) {
+                    //
+                    // Lets face it. This is going to be
+                    // Infinity. Cut to the chase.
+                    //
+                    return (isNegative) ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
+                }
+                if ((exp & 15) != 0) {
+                    dValue *= SMALL_10_POW[exp & 15];
+                }
+                if ((exp >>= 4) != 0) {
+                    int j;
+                    for (j = 0; exp > 0; j++, exp >>= 1) {
+                        if ((exp & 1) != 0) {
+                            dValue *= BIG_10_POW[j];
+                        }
+                    }
+                }
+            } else if (exp < 0) {
+                exp = -exp;
+                if (decExponent < SINGLE_MIN_DECIMAL_EXPONENT - 1) {
+                    //
+                    // Lets face it. This is going to be
+                    // zero. Cut to the chase.
+                    //
+                    return (isNegative) ? -0.0f : 0.0f;
+                }
+                if ((exp & 15) != 0) {
+                    dValue /= SMALL_10_POW[exp & 15];
+                }
+                if ((exp >>= 4) != 0) {
+                    int j;
+                    for (j = 0; exp > 0; j++, exp >>= 1) {
+                        if ((exp & 1) != 0) {
+                            dValue *= TINY_10_POW[j];
+                        }
+                    }
+                }
+            }
+            fValue = Math.max(Float.MIN_VALUE, Math.min(Float.MAX_VALUE, (float) dValue));
+
+            //
+            // fValue is now approximately the result.
+            // The hard part is adjusting it, by comparison
+            // with FDBigInteger arithmetic.
+            // Formulate the EXACT big-number result as
+            // bigD0 * 10^exp
+            //
+            if (nDigits > SINGLE_MAX_NDIGITS) {
+                nDigits = SINGLE_MAX_NDIGITS + 1;
+                digits[SINGLE_MAX_NDIGITS] = '1';
+            }
+            FDBigInteger bigD0 = new FDBigInteger(iValue, digits, kDigits, nDigits);
+            exp = decExponent - nDigits;
+
+            int ieeeBits = Float.floatToRawIntBits(fValue); // IEEE-754 bits of float candidate
+            final int B5 = Math.max(0, -exp); // powers of 5 in bigB, value is not modified inside correctionLoop
+            final int D5 = Math.max(0, exp); // powers of 5 in bigD, value is not modified inside correctionLoop
+            bigD0 = bigD0.multByPow52(D5, 0);
+            bigD0.makeImmutable();   // prevent bigD0 modification inside correctionLoop
+            FDBigInteger bigD = null;
+            int prevD2 = 0;
+
+            correctionLoop:
+            while (true) {
+                // here ieeeBits can't be NaN, Infinity or zero
+                int binexp = ieeeBits >>> SINGLE_EXP_SHIFT;
+                int bigBbits = ieeeBits & FloatConsts.SIGNIF_BIT_MASK;
+                if (binexp > 0) {
+                    bigBbits |= SINGLE_FRACT_HOB;
+                } else { // Normalize denormalized numbers.
+                    assert bigBbits != 0 : bigBbits; // floatToBigInt(0.0)
+                    int leadingZeros = Integer.numberOfLeadingZeros(bigBbits);
+                    int shift = leadingZeros - (31 - SINGLE_EXP_SHIFT);
+                    bigBbits <<= shift;
+                    binexp = 1 - shift;
+                }
+                binexp -= FloatConsts.EXP_BIAS;
+                int lowOrderZeros = Integer.numberOfTrailingZeros(bigBbits);
+                bigBbits >>>= lowOrderZeros;
+                final int bigIntExp = binexp - SINGLE_EXP_SHIFT + lowOrderZeros;
+                final int bigIntNBits = SINGLE_EXP_SHIFT + 1 - lowOrderZeros;
+
+                //
+                // Scale bigD, bigB appropriately for
+                // big-integer operations.
+                // Naively, we multiply by powers of ten
+                // and powers of two. What we actually do
+                // is keep track of the powers of 5 and
+                // powers of 2 we would use, then factor out
+                // common divisors before doing the work.
+                //
+                int B2 = B5; // powers of 2 in bigB
+                int D2 = D5; // powers of 2 in bigD
+                int Ulp2;   // powers of 2 in halfUlp.
+                if (bigIntExp >= 0) {
+                    B2 += bigIntExp;
+                } else {
+                    D2 -= bigIntExp;
+                }
+                Ulp2 = B2;
+                // shift bigB and bigD left by a number s. t.
+                // halfUlp is still an integer.
+                int hulpbias;
+                if (binexp <= -FloatConsts.EXP_BIAS) {
+                    // This is going to be a denormalized number
+                    // (if not actually zero).
+                    // half an ULP is at 2^-(FloatConsts.EXP_BIAS+SINGLE_EXP_SHIFT+1)
+                    hulpbias = binexp + lowOrderZeros + FloatConsts.EXP_BIAS;
+                } else {
+                    hulpbias = 1 + lowOrderZeros;
+                }
+                B2 += hulpbias;
+                D2 += hulpbias;
+                // if there are common factors of 2, we might just as well
+                // factor them out, as they add nothing useful.
+                int common2 = Math.min(B2, Math.min(D2, Ulp2));
+                B2 -= common2;
+                D2 -= common2;
+                Ulp2 -= common2;
+                // do multiplications by powers of 5 and 2
+                FDBigInteger bigB = FDBigInteger.valueOfMulPow52(bigBbits, B5, B2);
+                if (bigD == null || prevD2 != D2) {
+                    bigD = bigD0.leftShift(D2);
+                    prevD2 = D2;
+                }
+                //
+                // to recap:
+                // bigB is the scaled-big-int version of our floating-point
+                // candidate.
+                // bigD is the scaled-big-int version of the exact value
+                // as we understand it.
+                // halfUlp is 1/2 an ulp of bigB, except for special cases
+                // of exact powers of 2
+                //
+                // the plan is to compare bigB with bigD, and if the difference
+                // is less than halfUlp, then we're satisfied. Otherwise,
+                // use the ratio of difference to halfUlp to calculate a fudge
+                // factor to add to the floating value, then go 'round again.
+                //
+                FDBigInteger diff;
+                int cmpResult;
+                boolean overvalue;
+                if ((cmpResult = bigB.cmp(bigD)) > 0) {
+                    overvalue = true; // our candidate is too big.
+                    diff = bigB.leftInplaceSub(bigD); // bigB is not user further - reuse
+                    if ((bigIntNBits == 1) && (bigIntExp > -FloatConsts.EXP_BIAS + 1)) {
+                        // candidate is a normalized exact power of 2 and
+                        // is too big (larger than Float.MIN_NORMAL). We will be subtracting.
+                        // For our purposes, ulp is the ulp of the
+                        // next smaller range.
+                        Ulp2 -= 1;
+                        if (Ulp2 < 0) {
+                            // rats. Cannot de-scale ulp this far.
+                            // must scale diff in other direction.
+                            Ulp2 = 0;
+                            diff = diff.leftShift(1);
+                        }
+                    }
+                } else if (cmpResult < 0) {
+                    overvalue = false; // our candidate is too small.
+                    diff = bigD.rightInplaceSub(bigB); // bigB is not user further - reuse
+                } else {
+                    // the candidate is exactly right!
+                    // this happens with surprising frequency
+                    break correctionLoop;
+                }
+                cmpResult = diff.cmpPow52(B5, Ulp2);
+                if ((cmpResult) < 0) {
+                    // difference is small.
+                    // this is close enough
+                    break correctionLoop;
+                } else if (cmpResult == 0) {
+                    // difference is exactly half an ULP
+                    // round to some other value maybe, then finish
+                    if ((ieeeBits & 1) != 0) { // half ties to even
+                        ieeeBits += overvalue ? -1 : 1; // nextDown or nextUp
+                    }
+                    break correctionLoop;
+                } else {
+                    // difference is non-trivial.
+                    // could scale addend by ratio of difference to
+                    // halfUlp here, if we bothered to compute that difference.
+                    // Most of the time ( I hope ) it is about 1 anyway.
+                    ieeeBits += overvalue ? -1 : 1; // nextDown or nextUp
+                    if (ieeeBits == 0 || ieeeBits == FloatConsts.EXP_BIT_MASK) { // 0.0 or Float.POSITIVE_INFINITY
+                        break correctionLoop; // oops. Fell off end of range.
+                    }
+                    continue; // try again.
+                }
+
+            }
+            if (isNegative) {
+                ieeeBits |= FloatConsts.SIGN_BIT_MASK;
+            }
+            return Float.intBitsToFloat(ieeeBits);
+        }
+
+
+        /**
+         * All the positive powers of 10 that can be
+         * represented exactly in double/float.
+         */
+        private static final double[] SMALL_10_POW = {
+            1.0e0,
+            1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5,
+            1.0e6, 1.0e7, 1.0e8, 1.0e9, 1.0e10,
+            1.0e11, 1.0e12, 1.0e13, 1.0e14, 1.0e15,
+            1.0e16, 1.0e17, 1.0e18, 1.0e19, 1.0e20,
+            1.0e21, 1.0e22
+        };
+
+        private static final float[] SINGLE_SMALL_10_POW = {
+            1.0e0f,
+            1.0e1f, 1.0e2f, 1.0e3f, 1.0e4f, 1.0e5f,
+            1.0e6f, 1.0e7f, 1.0e8f, 1.0e9f, 1.0e10f
+        };
+
+        private static final double[] BIG_10_POW = {
+            1e16, 1e32, 1e64, 1e128, 1e256 };
+        private static final double[] TINY_10_POW = {
+            1e-16, 1e-32, 1e-64, 1e-128, 1e-256 };
+
+        private static final int MAX_SMALL_TEN = SMALL_10_POW.length-1;
+        private static final int SINGLE_MAX_SMALL_TEN = SINGLE_SMALL_10_POW.length-1;
+
+    }
+
+    /**
+     * Returns a <code>BinaryToASCIIConverter</code> for a <code>double</code>.
+     * The returned object is a <code>ThreadLocal</code> variable of this class.
+     *
+     * @param d The double precision value to convert.
+     * @return The converter.
+     */
+    public static BinaryToASCIIConverter getBinaryToASCIIConverter(double d) {
+        return getBinaryToASCIIConverter(d, true);
+    }
+
+    /**
+     * Returns a <code>BinaryToASCIIConverter</code> for a <code>double</code>.
+     * The returned object is a <code>ThreadLocal</code> variable of this class.
+     *
+     * @param d The double precision value to convert.
+     * @param isCompatibleFormat
+     * @return The converter.
+     */
+    static BinaryToASCIIConverter getBinaryToASCIIConverter(double d, boolean isCompatibleFormat) {
+        long dBits = Double.doubleToRawLongBits(d);
+        boolean isNegative = (dBits&DoubleConsts.SIGN_BIT_MASK) != 0; // discover sign
+        long fractBits = dBits & DoubleConsts.SIGNIF_BIT_MASK;
+        int  binExp = (int)( (dBits&DoubleConsts.EXP_BIT_MASK) >> EXP_SHIFT );
+        // Discover obvious special cases of NaN and Infinity.
+        if ( binExp == (int)(DoubleConsts.EXP_BIT_MASK>>EXP_SHIFT) ) {
+            if ( fractBits == 0L ){
+                return isNegative ? B2AC_NEGATIVE_INFINITY : B2AC_POSITIVE_INFINITY;
+            } else {
+                return B2AC_NOT_A_NUMBER;
+            }
+        }
+        // Finish unpacking
+        // Normalize denormalized numbers.
+        // Insert assumed high-order bit for normalized numbers.
+        // Subtract exponent bias.
+        int  nSignificantBits;
+        if ( binExp == 0 ){
+            if ( fractBits == 0L ){
+                // not a denorm, just a 0!
+                return isNegative ? B2AC_NEGATIVE_ZERO : B2AC_POSITIVE_ZERO;
+            }
+            int leadingZeros = Long.numberOfLeadingZeros(fractBits);
+            int shift = leadingZeros-(63-EXP_SHIFT);
+            fractBits <<= shift;
+            binExp = 1 - shift;
+            nSignificantBits =  64-leadingZeros; // recall binExp is  - shift count.
+        } else {
+            fractBits |= FRACT_HOB;
+            nSignificantBits = EXP_SHIFT+1;
+        }
+        binExp -= DoubleConsts.EXP_BIAS;
+        BinaryToASCIIBuffer buf = getBinaryToASCIIBuffer();
+        buf.setSign(isNegative);
+        // call the routine that actually does all the hard work.
+        buf.dtoa(binExp, fractBits, nSignificantBits, isCompatibleFormat);
+        return buf;
+    }
+
+    private static BinaryToASCIIConverter getBinaryToASCIIConverter(float f) {
+        int fBits = Float.floatToRawIntBits( f );
+        boolean isNegative = (fBits&FloatConsts.SIGN_BIT_MASK) != 0;
+        int fractBits = fBits&FloatConsts.SIGNIF_BIT_MASK;
+        int binExp = (fBits&FloatConsts.EXP_BIT_MASK) >> SINGLE_EXP_SHIFT;
+        // Discover obvious special cases of NaN and Infinity.
+        if ( binExp == (FloatConsts.EXP_BIT_MASK>>SINGLE_EXP_SHIFT) ) {
+            if ( fractBits == 0L ){
+                return isNegative ? B2AC_NEGATIVE_INFINITY : B2AC_POSITIVE_INFINITY;
+            } else {
+                return B2AC_NOT_A_NUMBER;
+            }
+        }
+        // Finish unpacking
+        // Normalize denormalized numbers.
+        // Insert assumed high-order bit for normalized numbers.
+        // Subtract exponent bias.
+        int  nSignificantBits;
+        if ( binExp == 0 ){
+            if ( fractBits == 0 ){
+                // not a denorm, just a 0!
+                return isNegative ? B2AC_NEGATIVE_ZERO : B2AC_POSITIVE_ZERO;
+            }
+            int leadingZeros = Integer.numberOfLeadingZeros(fractBits);
+            int shift = leadingZeros-(31-SINGLE_EXP_SHIFT);
+            fractBits <<= shift;
+            binExp = 1 - shift;
+            nSignificantBits =  32 - leadingZeros; // recall binExp is  - shift count.
+        } else {
+            fractBits |= SINGLE_FRACT_HOB;
+            nSignificantBits = SINGLE_EXP_SHIFT+1;
+        }
+        binExp -= FloatConsts.EXP_BIAS;
+        BinaryToASCIIBuffer buf = getBinaryToASCIIBuffer();
+        buf.setSign(isNegative);
+        // call the routine that actually does all the hard work.
+        buf.dtoa(binExp, ((long)fractBits)<<(EXP_SHIFT-SINGLE_EXP_SHIFT), nSignificantBits, true);
+        return buf;
+    }
+
+    @SuppressWarnings("fallthrough")
+    static ASCIIToBinaryConverter readJavaFormatString( String in ) throws NumberFormatException {
+        boolean isNegative = false;
+        boolean signSeen   = false;
+        int     decExp;
+        char    c;
+
+    parseNumber:
+        try{
+            in = in.trim(); // don't fool around with white space.
+                            // throws NullPointerException if null
+            int len = in.length();
+            if ( len == 0 ) {
+                throw new NumberFormatException("empty String");
+            }
+            int i = 0;
+            switch (in.charAt(i)){
+            case '-':
+                isNegative = true;
+                //FALLTHROUGH
+            case '+':
+                i++;
+                signSeen = true;
+            }
+            c = in.charAt(i);
+            if(c == 'N') { // Check for NaN
+                if((len-i)==NAN_LENGTH && in.indexOf(NAN_REP,i)==i) {
+                    return A2BC_NOT_A_NUMBER;
+                }
+                // something went wrong, throw exception
+                break parseNumber;
+            } else if(c == 'I') { // Check for Infinity strings
+                if((len-i)==INFINITY_LENGTH && in.indexOf(INFINITY_REP,i)==i) {
+                    return isNegative? A2BC_NEGATIVE_INFINITY : A2BC_POSITIVE_INFINITY;
+                }
+                // something went wrong, throw exception
+                break parseNumber;
+            } else if (c == '0')  { // check for hexadecimal floating-point number
+                if (len > i+1 ) {
+                    char ch = in.charAt(i+1);
+                    if (ch == 'x' || ch == 'X' ) { // possible hex string
+                        return parseHexString(in);
+                    }
+                }
+            }  // look for and process decimal floating-point string
+
+            char[] digits = new char[ len ];
+            int    nDigits= 0;
+            boolean decSeen = false;
+            int decPt = 0;
+            int nLeadZero = 0;
+            int nTrailZero= 0;
+
+        skipLeadingZerosLoop:
+            while (i < len) {
+                c = in.charAt(i);
+                if (c == '0') {
+                    nLeadZero++;
+                } else if (c == '.') {
+                    if (decSeen) {
+                        // already saw one ., this is the 2nd.
+                        throw new NumberFormatException("multiple points");
+                    }
+                    decPt = i;
+                    if (signSeen) {
+                        decPt -= 1;
+                    }
+                    decSeen = true;
+                } else {
+                    break skipLeadingZerosLoop;
+                }
+                i++;
+            }
+        digitLoop:
+            while (i < len) {
+                c = in.charAt(i);
+                if (c >= '1' && c <= '9') {
+                    digits[nDigits++] = c;
+                    nTrailZero = 0;
+                } else if (c == '0') {
+                    digits[nDigits++] = c;
+                    nTrailZero++;
+                } else if (c == '.') {
+                    if (decSeen) {
+                        // already saw one ., this is the 2nd.
+                        throw new NumberFormatException("multiple points");
+                    }
+                    decPt = i;
+                    if (signSeen) {
+                        decPt -= 1;
+                    }
+                    decSeen = true;
+                } else {
+                    break digitLoop;
+                }
+                i++;
+            }
+            nDigits -=nTrailZero;
+            //
+            // At this point, we've scanned all the digits and decimal
+            // point we're going to see. Trim off leading and trailing
+            // zeros, which will just confuse us later, and adjust
+            // our initial decimal exponent accordingly.
+            // To review:
+            // we have seen i total characters.
+            // nLeadZero of them were zeros before any other digits.
+            // nTrailZero of them were zeros after any other digits.
+            // if ( decSeen ), then a . was seen after decPt characters
+            // ( including leading zeros which have been discarded )
+            // nDigits characters were neither lead nor trailing
+            // zeros, nor point
+            //
+            //
+            // special hack: if we saw no non-zero digits, then the
+            // answer is zero!
+            // Unfortunately, we feel honor-bound to keep parsing!
+            //
+            boolean isZero = (nDigits == 0);
+            if ( isZero &&  nLeadZero == 0 ){
+                // we saw NO DIGITS AT ALL,
+                // not even a crummy 0!
+                // this is not allowed.
+                break parseNumber; // go throw exception
+            }
+            //
+            // Our initial exponent is decPt, adjusted by the number of
+            // discarded zeros. Or, if there was no decPt,
+            // then its just nDigits adjusted by discarded trailing zeros.
+            //
+            if ( decSeen ){
+                decExp = decPt - nLeadZero;
+            } else {
+                decExp = nDigits + nTrailZero;
+            }
+
+            //
+            // Look for 'e' or 'E' and an optionally signed integer.
+            //
+            if ( (i < len) &&  (((c = in.charAt(i) )=='e') || (c == 'E') ) ){
+                int expSign = 1;
+                int expVal  = 0;
+                int reallyBig = Integer.MAX_VALUE / 10;
+                boolean expOverflow = false;
+                switch( in.charAt(++i) ){
+                case '-':
+                    expSign = -1;
+                    //FALLTHROUGH
+                case '+':
+                    i++;
+                }
+                int expAt = i;
+            expLoop:
+                while ( i < len  ){
+                    if ( expVal >= reallyBig ){
+                        // the next character will cause integer
+                        // overflow.
+                        expOverflow = true;
+                    }
+                    c = in.charAt(i++);
+                    if(c>='0' && c<='9') {
+                        expVal = expVal*10 + ( (int)c - (int)'0' );
+                    } else {
+                        i--;           // back up.
+                        break expLoop; // stop parsing exponent.
+                    }
+                }
+                int expLimit = BIG_DECIMAL_EXPONENT + nDigits + nTrailZero;
+                if (expOverflow || (expVal > expLimit)) {
+                    // There is still a chance that the exponent will be safe to
+                    // use: if it would eventually decrease due to a negative
+                    // decExp, and that number is below the limit.  We check for
+                    // that here.
+                    if (!expOverflow && (expSign == 1 && decExp < 0)
+                            && (expVal + decExp) < expLimit) {
+                        // Cannot overflow: adding a positive and negative number.
+                        decExp += expVal;
+                    } else {
+                        //
+                        // The intent here is to end up with
+                        // infinity or zero, as appropriate.
+                        // The reason for yielding such a small decExponent,
+                        // rather than something intuitive such as
+                        // expSign*Integer.MAX_VALUE, is that this value
+                        // is subject to further manipulation in
+                        // doubleValue() and floatValue(), and I don't want
+                        // it to be able to cause overflow there!
+                        // (The only way we can get into trouble here is for
+                        // really outrageous nDigits+nTrailZero, such as 2
+                        // billion.)
+                        //
+                        decExp = expSign * expLimit;
+                    }
+                } else {
+                    // this should not overflow, since we tested
+                    // for expVal > (MAX+N), where N >= abs(decExp)
+                    decExp = decExp + expSign*expVal;
+                }
+
+                // if we saw something not a digit ( or end of string )
+                // after the [Ee][+-], without seeing any digits at all
+                // this is certainly an error. If we saw some digits,
+                // but then some trailing garbage, that might be ok.
+                // so we just fall through in that case.
+                // HUMBUG
+                if ( i == expAt ) {
+                    break parseNumber; // certainly bad
+                }
+            }
+            //
+            // We parsed everything we could.
+            // If there are leftovers, then this is not good input!
+            //
+            if ( i < len &&
+                ((i != len - 1) ||
+                (in.charAt(i) != 'f' &&
+                 in.charAt(i) != 'F' &&
+                 in.charAt(i) != 'd' &&
+                 in.charAt(i) != 'D'))) {
+                break parseNumber; // go throw exception
+            }
+            if(isZero) {
+                return isNegative ? A2BC_NEGATIVE_ZERO : A2BC_POSITIVE_ZERO;
+            }
+            return new ASCIIToBinaryBuffer(isNegative, decExp, digits, nDigits);
+        } catch ( StringIndexOutOfBoundsException e ){ }
+        throw new NumberFormatException("For input string: \"" + in + "\"");
+    }
+
+    private static class HexFloatPattern {
+        /**
+         * Grammar is compatible with hexadecimal floating-point constants
+         * described in section 6.4.4.2 of the C99 specification.
+         */
+        private static final Pattern VALUE = Pattern.compile(
+                   //1           234                   56                7                   8      9
+                    "([-+])?0[xX](((\\p{XDigit}+)\\.?)|((\\p{XDigit}*)\\.(\\p{XDigit}+)))[pP]([-+])?(\\p{Digit}+)[fFdD]?"
+                    );
+    }
+
+    /**
+     * Converts string s to a suitable floating decimal; uses the
+     * double constructor and sets the roundDir variable appropriately
+     * in case the value is later converted to a float.
+     *
+     * @param s The <code>String</code> to parse.
+     */
+   static ASCIIToBinaryConverter parseHexString(String s) {
+            // Verify string is a member of the hexadecimal floating-point
+            // string language.
+            Matcher m = HexFloatPattern.VALUE.matcher(s);
+            boolean validInput = m.matches();
+            if (!validInput) {
+                // Input does not match pattern
+                throw new NumberFormatException("For input string: \"" + s + "\"");
+            } else { // validInput
+                //
+                // We must isolate the sign, significand, and exponent
+                // fields.  The sign value is straightforward.  Since
+                // floating-point numbers are stored with a normalized
+                // representation, the significand and exponent are
+                // interrelated.
+                //
+                // After extracting the sign, we normalized the
+                // significand as a hexadecimal value, calculating an
+                // exponent adjust for any shifts made during
+                // normalization.  If the significand is zero, the
+                // exponent doesn't need to be examined since the output
+                // will be zero.
+                //
+                // Next the exponent in the input string is extracted.
+                // Afterwards, the significand is normalized as a *binary*
+                // value and the input value's normalized exponent can be
+                // computed.  The significand bits are copied into a
+                // double significand; if the string has more logical bits
+                // than can fit in a double, the extra bits affect the
+                // round and sticky bits which are used to round the final
+                // value.
+                //
+                //  Extract significand sign
+                String group1 = m.group(1);
+                boolean isNegative = ((group1 != null) && group1.equals("-"));
+
+                //  Extract Significand magnitude
+                //
+                // Based on the form of the significand, calculate how the
+                // binary exponent needs to be adjusted to create a
+                // normalized//hexadecimal* floating-point number; that
+                // is, a number where there is one nonzero hex digit to
+                // the left of the (hexa)decimal point.  Since we are
+                // adjusting a binary, not hexadecimal exponent, the
+                // exponent is adjusted by a multiple of 4.
+                //
+                // There are a number of significand scenarios to consider;
+                // letters are used in indicate nonzero digits:
+                //
+                // 1. 000xxxx       =>      x.xxx   normalized
+                //    increase exponent by (number of x's - 1)*4
+                //
+                // 2. 000xxx.yyyy =>        x.xxyyyy        normalized
+                //    increase exponent by (number of x's - 1)*4
+                //
+                // 3. .000yyy  =>   y.yy    normalized
+                //    decrease exponent by (number of zeros + 1)*4
+                //
+                // 4. 000.00000yyy => y.yy normalized
+                //    decrease exponent by (number of zeros to right of point + 1)*4
+                //
+                // If the significand is exactly zero, return a properly
+                // signed zero.
+                //
+
+                String significandString = null;
+                int signifLength = 0;
+                int exponentAdjust = 0;
+                {
+                    int leftDigits = 0; // number of meaningful digits to
+                    // left of "decimal" point
+                    // (leading zeros stripped)
+                    int rightDigits = 0; // number of digits to right of
+                    // "decimal" point; leading zeros
+                    // must always be accounted for
+                    //
+                    // The significand is made up of either
+                    //
+                    // 1. group 4 entirely (integer portion only)
+                    //
+                    // OR
+                    //
+                    // 2. the fractional portion from group 7 plus any
+                    // (optional) integer portions from group 6.
+                    //
+                    String group4;
+                    if ((group4 = m.group(4)) != null) {  // Integer-only significand
+                        // Leading zeros never matter on the integer portion
+                        significandString = stripLeadingZeros(group4);
+                        leftDigits = significandString.length();
+                    } else {
+                        // Group 6 is the optional integer; leading zeros
+                        // never matter on the integer portion
+                        String group6 = stripLeadingZeros(m.group(6));
+                        leftDigits = group6.length();
+
+                        // fraction
+                        String group7 = m.group(7);
+                        rightDigits = group7.length();
+
+                        // Turn "integer.fraction" into "integer"+"fraction"
+                        significandString =
+                                ((group6 == null) ? "" : group6) + // is the null
+                                        // check necessary?
+                                        group7;
+                    }
+
+                    significandString = stripLeadingZeros(significandString);
+                    signifLength = significandString.length();
+
+                    //
+                    // Adjust exponent as described above
+                    //
+                    if (leftDigits >= 1) {  // Cases 1 and 2
+                        exponentAdjust = 4 * (leftDigits - 1);
+                    } else {                // Cases 3 and 4
+                        exponentAdjust = -4 * (rightDigits - signifLength + 1);
+                    }
+
+                    // If the significand is zero, the exponent doesn't
+                    // matter; return a properly signed zero.
+
+                    if (signifLength == 0) { // Only zeros in input
+                        return isNegative ? A2BC_NEGATIVE_ZERO : A2BC_POSITIVE_ZERO;
+                    }
+                }
+
+                //  Extract Exponent
+                //
+                // Use an int to read in the exponent value; this should
+                // provide more than sufficient range for non-contrived
+                // inputs.  If reading the exponent in as an int does
+                // overflow, examine the sign of the exponent and
+                // significand to determine what to do.
+                //
+                String group8 = m.group(8);
+                boolean positiveExponent = (group8 == null) || group8.equals("+");
+                long unsignedRawExponent;
+                try {
+                    unsignedRawExponent = Integer.parseInt(m.group(9));
+                }
+                catch (NumberFormatException e) {
+                    // At this point, we know the exponent is
+                    // syntactically well-formed as a sequence of
+                    // digits.  Therefore, if an NumberFormatException
+                    // is thrown, it must be due to overflowing int's
+                    // range.  Also, at this point, we have already
+                    // checked for a zero significand.  Thus the signs
+                    // of the exponent and significand determine the
+                    // final result:
+                    //
+                    //                      significand
+                    //                      +               -
+                    // exponent     +       +infinity       -infinity
+                    //              -       +0.0            -0.0
+                    return isNegative ?
+                              (positiveExponent ? A2BC_NEGATIVE_INFINITY : A2BC_NEGATIVE_ZERO)
+                            : (positiveExponent ? A2BC_POSITIVE_INFINITY : A2BC_POSITIVE_ZERO);
+
+                }
+
+                long rawExponent =
+                        (positiveExponent ? 1L : -1L) * // exponent sign
+                                unsignedRawExponent;            // exponent magnitude
+
+                // Calculate partially adjusted exponent
+                long exponent = rawExponent + exponentAdjust;
+
+                // Starting copying non-zero bits into proper position in
+                // a long; copy explicit bit too; this will be masked
+                // later for normal values.
+
+                boolean round = false;
+                boolean sticky = false;
+                int nextShift = 0;
+                long significand = 0L;
+                // First iteration is different, since we only copy
+                // from the leading significand bit; one more exponent
+                // adjust will be needed...
+
+                // IMPORTANT: make leadingDigit a long to avoid
+                // surprising shift semantics!
+                long leadingDigit = getHexDigit(significandString, 0);
+
+                //
+                // Left shift the leading digit (53 - (bit position of
+                // leading 1 in digit)); this sets the top bit of the
+                // significand to 1.  The nextShift value is adjusted
+                // to take into account the number of bit positions of
+                // the leadingDigit actually used.  Finally, the
+                // exponent is adjusted to normalize the significand
+                // as a binary value, not just a hex value.
+                //
+                if (leadingDigit == 1) {
+                    significand |= leadingDigit << 52;
+                    nextShift = 52 - 4;
+                    // exponent += 0
+                } else if (leadingDigit <= 3) { // [2, 3]
+                    significand |= leadingDigit << 51;
+                    nextShift = 52 - 5;
+                    exponent += 1;
+                } else if (leadingDigit <= 7) { // [4, 7]
+                    significand |= leadingDigit << 50;
+                    nextShift = 52 - 6;
+                    exponent += 2;
+                } else if (leadingDigit <= 15) { // [8, f]
+                    significand |= leadingDigit << 49;
+                    nextShift = 52 - 7;
+                    exponent += 3;
+                } else {
+                    throw new AssertionError("Result from digit conversion too large!");
+                }
+                // The preceding if-else could be replaced by a single
+                // code block based on the high-order bit set in
+                // leadingDigit.  Given leadingOnePosition,
+
+                // significand |= leadingDigit << (SIGNIFICAND_WIDTH - leadingOnePosition);
+                // nextShift = 52 - (3 + leadingOnePosition);
+                // exponent += (leadingOnePosition-1);
+
+                //
+                // Now the exponent variable is equal to the normalized
+                // binary exponent.  Code below will make representation
+                // adjustments if the exponent is incremented after
+                // rounding (includes overflows to infinity) or if the
+                // result is subnormal.
+                //
+
+                // Copy digit into significand until the significand can't
+                // hold another full hex digit or there are no more input
+                // hex digits.
+                int i = 0;
+                for (i = 1;
+                     i < signifLength && nextShift >= 0;
+                     i++) {
+                    long currentDigit = getHexDigit(significandString, i);
+                    significand |= (currentDigit << nextShift);
+                    nextShift -= 4;
+                }
+
+                // After the above loop, the bulk of the string is copied.
+                // Now, we must copy any partial hex digits into the
+                // significand AND compute the round bit and start computing
+                // sticky bit.
+
+                if (i < signifLength) { // at least one hex input digit exists
+                    long currentDigit = getHexDigit(significandString, i);
+
+                    // from nextShift, figure out how many bits need
+                    // to be copied, if any
+                    switch (nextShift) { // must be negative
+                        case -1:
+                            // three bits need to be copied in; can
+                            // set round bit
+                            significand |= ((currentDigit & 0xEL) >> 1);
+                            round = (currentDigit & 0x1L) != 0L;
+                            break;
+
+                        case -2:
+                            // two bits need to be copied in; can
+                            // set round and start sticky
+                            significand |= ((currentDigit & 0xCL) >> 2);
+                            round = (currentDigit & 0x2L) != 0L;
+                            sticky = (currentDigit & 0x1L) != 0;
+                            break;
+
+                        case -3:
+                            // one bit needs to be copied in
+                            significand |= ((currentDigit & 0x8L) >> 3);
+                            // Now set round and start sticky, if possible
+                            round = (currentDigit & 0x4L) != 0L;
+                            sticky = (currentDigit & 0x3L) != 0;
+                            break;
+
+                        case -4:
+                            // all bits copied into significand; set
+                            // round and start sticky
+                            round = ((currentDigit & 0x8L) != 0);  // is top bit set?
+                            // nonzeros in three low order bits?
+                            sticky = (currentDigit & 0x7L) != 0;
+                            break;
+
+                        default:
+                            throw new AssertionError("Unexpected shift distance remainder.");
+                            // break;
+                    }
+
+                    // Round is set; sticky might be set.
+
+                    // For the sticky bit, it suffices to check the
+                    // current digit and test for any nonzero digits in
+                    // the remaining unprocessed input.
+                    i++;
+                    while (i < signifLength && !sticky) {
+                        currentDigit = getHexDigit(significandString, i);
+                        sticky = sticky || (currentDigit != 0);
+                        i++;
+                    }
+
+                }
+                // else all of string was seen, round and sticky are
+                // correct as false.
+
+                // Float calculations
+                int floatBits = isNegative ? FloatConsts.SIGN_BIT_MASK : 0;
+                if (exponent >= FloatConsts.MIN_EXPONENT) {
+                    if (exponent > FloatConsts.MAX_EXPONENT) {
+                        // Float.POSITIVE_INFINITY
+                        floatBits |= FloatConsts.EXP_BIT_MASK;
+                    } else {
+                        int threshShift = DoubleConsts.SIGNIFICAND_WIDTH - FloatConsts.SIGNIFICAND_WIDTH - 1;
+                        boolean floatSticky = (significand & ((1L << threshShift) - 1)) != 0 || round || sticky;
+                        int iValue = (int) (significand >>> threshShift);
+                        if ((iValue & 3) != 1 || floatSticky) {
+                            iValue++;
+                        }
+                        floatBits |= (((((int) exponent) + (FloatConsts.EXP_BIAS - 1))) << SINGLE_EXP_SHIFT) + (iValue >> 1);
+                    }
+                } else {
+                    if (exponent < FloatConsts.MIN_SUB_EXPONENT - 1) {
+                        // 0
+                    } else {
+                        // exponent == -127 ==> threshShift = 53 - 2 + (-149) - (-127) = 53 - 24
+                        int threshShift = (int) ((DoubleConsts.SIGNIFICAND_WIDTH - 2 + FloatConsts.MIN_SUB_EXPONENT) - exponent);
+                        assert threshShift >= DoubleConsts.SIGNIFICAND_WIDTH - FloatConsts.SIGNIFICAND_WIDTH;
+                        assert threshShift < DoubleConsts.SIGNIFICAND_WIDTH;
+                        boolean floatSticky = (significand & ((1L << threshShift) - 1)) != 0 || round || sticky;
+                        int iValue = (int) (significand >>> threshShift);
+                        if ((iValue & 3) != 1 || floatSticky) {
+                            iValue++;
+                        }
+                        floatBits |= iValue >> 1;
+                    }
+                }
+                float fValue = Float.intBitsToFloat(floatBits);
+
+                // Check for overflow and update exponent accordingly.
+                if (exponent > DoubleConsts.MAX_EXPONENT) {         // Infinite result
+                    // overflow to properly signed infinity
+                    return isNegative ? A2BC_NEGATIVE_INFINITY : A2BC_POSITIVE_INFINITY;
+                } else {  // Finite return value
+                    if (exponent <= DoubleConsts.MAX_EXPONENT && // (Usually) normal result
+                            exponent >= DoubleConsts.MIN_EXPONENT) {
+
+                        // The result returned in this block cannot be a
+                        // zero or subnormal; however after the
+                        // significand is adjusted from rounding, we could
+                        // still overflow in infinity.
+
+                        // AND exponent bits into significand; if the
+                        // significand is incremented and overflows from
+                        // rounding, this combination will update the
+                        // exponent correctly, even in the case of
+                        // Double.MAX_VALUE overflowing to infinity.
+
+                        significand = ((( exponent +
+                                (long) DoubleConsts.EXP_BIAS) <<
+                                (DoubleConsts.SIGNIFICAND_WIDTH - 1))
+                                & DoubleConsts.EXP_BIT_MASK) |
+                                (DoubleConsts.SIGNIF_BIT_MASK & significand);
+
+                    } else {  // Subnormal or zero
+                        // (exponent < DoubleConsts.MIN_EXPONENT)
+
+                        if (exponent < (DoubleConsts.MIN_SUB_EXPONENT - 1)) {
+                            // No way to round back to nonzero value
+                            // regardless of significand if the exponent is
+                            // less than -1075.
+                            return isNegative ? A2BC_NEGATIVE_ZERO : A2BC_POSITIVE_ZERO;
+                        } else { //  -1075 <= exponent <= MIN_EXPONENT -1 = -1023
+                            //
+                            // Find bit position to round to; recompute
+                            // round and sticky bits, and shift
+                            // significand right appropriately.
+                            //
+
+                            sticky = sticky || round;
+                            round = false;
+
+                            // Number of bits of significand to preserve is
+                            // exponent - abs_min_exp +1
+                            // check:
+                            // -1075 +1074 + 1 = 0
+                            // -1023 +1074 + 1 = 52
+
+                            int bitsDiscarded = 53 -
+                                    ((int) exponent - DoubleConsts.MIN_SUB_EXPONENT + 1);
+                            assert bitsDiscarded >= 1 && bitsDiscarded <= 53;
+
+                            // What to do here:
+                            // First, isolate the new round bit
+                            round = (significand & (1L << (bitsDiscarded - 1))) != 0L;
+                            if (bitsDiscarded > 1) {
+                                // create mask to update sticky bits; low
+                                // order bitsDiscarded bits should be 1
+                                long mask = ~((~0L) << (bitsDiscarded - 1));
+                                sticky = sticky || ((significand & mask) != 0L);
+                            }
+
+                            // Now, discard the bits
+                            significand = significand >> bitsDiscarded;
+
+                            significand = ((((long) (DoubleConsts.MIN_EXPONENT - 1) + // subnorm exp.
+                                    (long) DoubleConsts.EXP_BIAS) <<
+                                    (DoubleConsts.SIGNIFICAND_WIDTH - 1))
+                                    & DoubleConsts.EXP_BIT_MASK) |
+                                    (DoubleConsts.SIGNIF_BIT_MASK & significand);
+                        }
+                    }
+
+                    // The significand variable now contains the currently
+                    // appropriate exponent bits too.
+
+                    //
+                    // Determine if significand should be incremented;
+                    // making this determination depends on the least
+                    // significant bit and the round and sticky bits.
+                    //
+                    // Round to nearest even rounding table, adapted from
+                    // table 4.7 in "Computer Arithmetic" by IsraelKoren.
+                    // The digit to the left of the "decimal" point is the
+                    // least significant bit, the digits to the right of
+                    // the point are the round and sticky bits
+                    //
+                    // Number       Round(x)
+                    // x0.00        x0.
+                    // x0.01        x0.
+                    // x0.10        x0.
+                    // x0.11        x1. = x0. +1
+                    // x1.00        x1.
+                    // x1.01        x1.
+                    // x1.10        x1. + 1
+                    // x1.11        x1. + 1
+                    //
+                    boolean leastZero = ((significand & 1L) == 0L);
+                    if ((leastZero && round && sticky) ||
+                            ((!leastZero) && round)) {
+                        significand++;
+                    }
+
+                    double value = isNegative ?
+                            Double.longBitsToDouble(significand | DoubleConsts.SIGN_BIT_MASK) :
+                            Double.longBitsToDouble(significand );
+
+                    return new PreparedASCIIToBinaryBuffer(value, fValue);
+                }
+            }
+    }
+
+    /**
+     * Returns <code>s</code> with any leading zeros removed.
+     */
+    static String stripLeadingZeros(String s) {
+//        return  s.replaceFirst("^0+", "");
+        if(!s.isEmpty() && s.charAt(0)=='0') {
+            for(int i=1; i<s.length(); i++) {
+                if(s.charAt(i)!='0') {
+                    return s.substring(i);
+                }
+            }
+            return "";
+        }
+        return s;
+    }
+
+    /**
+     * Extracts a hexadecimal digit from position <code>position</code>
+     * of string <code>s</code>.
+     */
+    static int getHexDigit(String s, int position) {
+        int value = Character.digit(s.charAt(position), 16);
+        if (value <= -1 || value >= 16) {
+            throw new AssertionError("Unexpected failure of digit conversion of " +
+                                     s.charAt(position));
+        }
+        return value;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/math/FormattedFloatingDecimal.java	Tue Dec 22 09:14:16 2015 -0800
@@ -0,0 +1,349 @@
+/*
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.math;
+
+import java.util.Arrays;
+
+public class FormattedFloatingDecimal{
+
+    public enum Form { SCIENTIFIC, COMPATIBLE, DECIMAL_FLOAT, GENERAL };
+
+
+    public static FormattedFloatingDecimal valueOf(double d, int precision, Form form){
+        FloatingDecimal.BinaryToASCIIConverter fdConverter =
+                FloatingDecimal.getBinaryToASCIIConverter(d, form == Form.COMPATIBLE);
+        return new FormattedFloatingDecimal(precision,form, fdConverter);
+    }
+
+    private int decExponentRounded;
+    private char[] mantissa;
+    private char[] exponent;
+
+    private static final ThreadLocal<Object> threadLocalCharBuffer =
+            new ThreadLocal<Object>() {
+                @Override
+                protected Object initialValue() {
+                    return new char[20];
+                }
+            };
+
+    private static char[] getBuffer(){
+        return (char[]) threadLocalCharBuffer.get();
+    }
+
+    private FormattedFloatingDecimal(int precision, Form form, FloatingDecimal.BinaryToASCIIConverter fdConverter) {
+        if (fdConverter.isExceptional()) {
+            this.mantissa = fdConverter.toJavaFormatString().toCharArray();
+            this.exponent = null;
+            return;
+        }
+        char[] digits = getBuffer();
+        int nDigits = fdConverter.getDigits(digits);
+        int decExp = fdConverter.getDecimalExponent();
+        int exp;
+        boolean isNegative = fdConverter.isNegative();
+        switch (form) {
+            case COMPATIBLE:
+                exp = decExp;
+                this.decExponentRounded = exp;
+                fillCompatible(precision, digits, nDigits, exp, isNegative);
+                break;
+            case DECIMAL_FLOAT:
+                exp = applyPrecision(decExp, digits, nDigits, decExp + precision);
+                fillDecimal(precision, digits, nDigits, exp, isNegative);
+                this.decExponentRounded = exp;
+                break;
+            case SCIENTIFIC:
+                exp = applyPrecision(decExp, digits, nDigits, precision + 1);
+                fillScientific(precision, digits, nDigits, exp, isNegative);
+                this.decExponentRounded = exp;
+                break;
+            case GENERAL:
+                exp = applyPrecision(decExp, digits, nDigits, precision);
+                // adjust precision to be the number of digits to right of decimal
+                // the real exponent to be output is actually exp - 1, not exp
+                if (exp - 1 < -4 || exp - 1 >= precision) {
+                    // form = Form.SCIENTIFIC;
+                    precision--;
+                    fillScientific(precision, digits, nDigits, exp, isNegative);
+                } else {
+                    // form = Form.DECIMAL_FLOAT;
+                    precision = precision - exp;
+                    fillDecimal(precision, digits, nDigits, exp, isNegative);
+                }
+                this.decExponentRounded = exp;
+                break;
+            default:
+                assert false;
+        }
+    }
+
+    // returns the exponent after rounding has been done by applyPrecision
+    public int getExponentRounded() {
+        return decExponentRounded - 1;
+    }
+
+    public char[] getMantissa(){
+        return mantissa;
+    }
+
+    public char[] getExponent(){
+        return exponent;
+    }
+
+    /**
+     * Returns new decExp in case of overflow.
+     */
+    private static int applyPrecision(int decExp, char[] digits, int nDigits, int prec) {
+        if (prec >= nDigits || prec < 0) {
+            // no rounding necessary
+            return decExp;
+        }
+        if (prec == 0) {
+            // only one digit (0 or 1) is returned because the precision
+            // excludes all significant digits
+            if (digits[0] >= '5') {
+                digits[0] = '1';
+                Arrays.fill(digits, 1, nDigits, '0');
+                return decExp + 1;
+            } else {
+                Arrays.fill(digits, 0, nDigits, '0');
+                return decExp;
+            }
+        }
+        int q = digits[prec];
+        if (q >= '5') {
+            int i = prec;
+            q = digits[--i];
+            if ( q == '9' ) {
+                while ( q == '9' && i > 0 ){
+                    q = digits[--i];
+                }
+                if ( q == '9' ){
+                    // carryout! High-order 1, rest 0s, larger exp.
+                    digits[0] = '1';
+                    Arrays.fill(digits, 1, nDigits, '0');
+                    return decExp+1;
+                }
+            }
+            digits[i] = (char)(q + 1);
+            Arrays.fill(digits, i+1, nDigits, '0');
+        } else {
+            Arrays.fill(digits, prec, nDigits, '0');
+        }
+        return decExp;
+    }
+
+    /**
+     * Fills mantissa and exponent char arrays for compatible format.
+     */
+    private void fillCompatible(int precision, char[] digits, int nDigits, int exp, boolean isNegative) {
+        int startIndex = isNegative ? 1 : 0;
+        if (exp > 0 && exp < 8) {
+            // print digits.digits.
+            if (nDigits < exp) {
+                int extraZeros = exp - nDigits;
+                mantissa = create(isNegative, nDigits + extraZeros + 2);
+                System.arraycopy(digits, 0, mantissa, startIndex, nDigits);
+                Arrays.fill(mantissa, startIndex + nDigits, startIndex + nDigits + extraZeros, '0');
+                mantissa[startIndex + nDigits + extraZeros] = '.';
+                mantissa[startIndex + nDigits + extraZeros+1] = '0';
+            } else if (exp < nDigits) {
+                int t = Math.min(nDigits - exp, precision);
+                mantissa = create(isNegative, exp + 1 + t);
+                System.arraycopy(digits, 0, mantissa, startIndex, exp);
+                mantissa[startIndex + exp ] = '.';
+                System.arraycopy(digits, exp, mantissa, startIndex+exp+1, t);
+            } else { // exp == digits.length
+                mantissa = create(isNegative, nDigits + 2);
+                System.arraycopy(digits, 0, mantissa, startIndex, nDigits);
+                mantissa[startIndex + nDigits ] = '.';
+                mantissa[startIndex + nDigits +1] = '0';
+            }
+        } else if (exp <= 0 && exp > -3) {
+            int zeros = Math.max(0, Math.min(-exp, precision));
+            int t = Math.max(0, Math.min(nDigits, precision + exp));
+            // write '0' s before the significant digits
+            if (zeros > 0) {
+                mantissa = create(isNegative, zeros + 2 + t);
+                mantissa[startIndex] = '0';
+                mantissa[startIndex+1] = '.';
+                Arrays.fill(mantissa, startIndex + 2, startIndex + 2 + zeros, '0');
+                if (t > 0) {
+                    // copy only when significant digits are within the precision
+                    System.arraycopy(digits, 0, mantissa, startIndex + 2 + zeros, t);
+                }
+            } else if (t > 0) {
+                mantissa = create(isNegative, zeros + 2 + t);
+                mantissa[startIndex] = '0';
+                mantissa[startIndex + 1] = '.';
+                // copy only when significant digits are within the precision
+                System.arraycopy(digits, 0, mantissa, startIndex + 2, t);
+            } else {
+                this.mantissa = create(isNegative, 1);
+                this.mantissa[startIndex] = '0';
+            }
+        } else {
+            if (nDigits > 1) {
+                mantissa = create(isNegative, nDigits + 1);
+                mantissa[startIndex] = digits[0];
+                mantissa[startIndex + 1] = '.';
+                System.arraycopy(digits, 1, mantissa, startIndex + 2, nDigits - 1);
+            } else {
+                mantissa = create(isNegative, 3);
+                mantissa[startIndex] = digits[0];
+                mantissa[startIndex + 1] = '.';
+                mantissa[startIndex + 2] = '0';
+            }
+            int e, expStartIntex;
+            boolean isNegExp = (exp <= 0);
+            if (isNegExp) {
+                e = -exp + 1;
+                expStartIntex = 1;
+            } else {
+                e = exp - 1;
+                expStartIntex = 0;
+            }
+            // decExponent has 1, 2, or 3, digits
+            if (e <= 9) {
+                exponent = create(isNegExp,1);
+                exponent[expStartIntex] = (char) (e + '0');
+            } else if (e <= 99) {
+                exponent = create(isNegExp,2);
+                exponent[expStartIntex] = (char) (e / 10 + '0');
+                exponent[expStartIntex+1] = (char) (e % 10 + '0');
+            } else {
+                exponent = create(isNegExp,3);
+                exponent[expStartIntex] = (char) (e / 100 + '0');
+                e %= 100;
+                exponent[expStartIntex+1] = (char) (e / 10 + '0');
+                exponent[expStartIntex+2] = (char) (e % 10 + '0');
+            }
+        }
+    }
+
+    private static char[] create(boolean isNegative, int size) {
+        if(isNegative) {
+            char[] r = new char[size +1];
+            r[0] = '-';
+            return r;
+        } else {
+            return new char[size];
+        }
+    }
+
+    /*
+     * Fills mantissa char arrays for DECIMAL_FLOAT format.
+     * Exponent should be equal to null.
+     */
+    private void fillDecimal(int precision, char[] digits, int nDigits, int exp, boolean isNegative) {
+        int startIndex = isNegative ? 1 : 0;
+        if (exp > 0) {
+            // print digits.digits.
+            if (nDigits < exp) {
+                mantissa = create(isNegative,exp);
+                System.arraycopy(digits, 0, mantissa, startIndex, nDigits);
+                Arrays.fill(mantissa, startIndex + nDigits, startIndex + exp, '0');
+                // Do not append ".0" for formatted floats since the user
+                // may request that it be omitted. It is added as necessary
+                // by the Formatter.
+            } else {
+                int t = Math.min(nDigits - exp, precision);
+                mantissa = create(isNegative, exp + (t > 0 ? (t + 1) : 0));
+                System.arraycopy(digits, 0, mantissa, startIndex, exp);
+                // Do not append ".0" for formatted floats since the user
+                // may request that it be omitted. It is added as necessary
+                // by the Formatter.
+                if (t > 0) {
+                    mantissa[startIndex + exp] = '.';
+                    System.arraycopy(digits, exp, mantissa, startIndex + exp + 1, t);
+                }
+            }
+        } else if (exp <= 0) {
+            int zeros = Math.max(0, Math.min(-exp, precision));
+            int t = Math.max(0, Math.min(nDigits, precision + exp));
+            // write '0' s before the significant digits
+            if (zeros > 0) {
+                mantissa = create(isNegative, zeros + 2 + t);
+                mantissa[startIndex] = '0';
+                mantissa[startIndex+1] = '.';
+                Arrays.fill(mantissa, startIndex + 2, startIndex + 2 + zeros, '0');
+                if (t > 0) {
+                    // copy only when significant digits are within the precision
+                    System.arraycopy(digits, 0, mantissa, startIndex + 2 + zeros, t);
+                }
+            } else if (t > 0) {
+                mantissa = create(isNegative, zeros + 2 + t);
+                mantissa[startIndex] = '0';
+                mantissa[startIndex + 1] = '.';
+                // copy only when significant digits are within the precision
+                System.arraycopy(digits, 0, mantissa, startIndex + 2, t);
+            } else {
+                this.mantissa = create(isNegative, 1);
+                this.mantissa[startIndex] = '0';
+            }
+        }
+    }
+
+    /**
+     * Fills mantissa and exponent char arrays for SCIENTIFIC format.
+     */
+    private void fillScientific(int precision, char[] digits, int nDigits, int exp, boolean isNegative) {
+        int startIndex = isNegative ? 1 : 0;
+        int t = Math.max(0, Math.min(nDigits - 1, precision));
+        if (t > 0) {
+            mantissa = create(isNegative, t + 2);
+            mantissa[startIndex] = digits[0];
+            mantissa[startIndex + 1] = '.';
+            System.arraycopy(digits, 1, mantissa, startIndex + 2, t);
+        } else {
+            mantissa = create(isNegative, 1);
+            mantissa[startIndex] = digits[0];
+        }
+        char expSign;
+        int e;
+        if (exp <= 0) {
+            expSign = '-';
+            e = -exp + 1;
+        } else {
+            expSign = '+' ;
+            e = exp - 1;
+        }
+        // decExponent has 1, 2, or 3, digits
+        if (e <= 9) {
+            exponent = new char[] { expSign,
+                    '0', (char) (e + '0') };
+        } else if (e <= 99) {
+            exponent = new char[] { expSign,
+                    (char) (e / 10 + '0'), (char) (e % 10 + '0') };
+        } else {
+            char hiExpChar = (char) (e / 100 + '0');
+            e %= 100;
+            exponent = new char[] { expSign,
+                    hiExpChar, (char) (e / 10 + '0'), (char) (e % 10 + '0') };
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/misc/CleanerImpl.java	Tue Dec 22 09:14:16 2015 -0800
@@ -0,0 +1,790 @@
+/*