am d3b74a8a: Delete RuntimeTest.test_gc.

* commit 'd3b74a8affe39699df64469c955d0e925e1566fb':
  Delete RuntimeTest.test_gc.
diff --git a/NOTICE b/NOTICE
index 951e506..5136b4b 100644
--- a/NOTICE
+++ b/NOTICE
@@ -104,3 +104,14 @@
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+   =========================================================================
+   ==  NOTICE file for the fdlibm License.                                   ==
+   =========================================================================
+
+Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+
+Developed at SunSoft, a Sun Microsystems, Inc. business.
+Permission to use, copy, modify, and distribute this
+software is freely granted, provided that this notice
+is preserved.
diff --git a/expectations/knownfailures.txt b/expectations/knownfailures.txt
index 918caab..c8a1b35 100644
--- a/expectations/knownfailures.txt
+++ b/expectations/knownfailures.txt
@@ -1419,14 +1419,6 @@
   name: "com.android.org.apache.harmony.logging.tests.java.util.logging.LevelTest#testSerializationCompatibility"
 },
 {
-  description: "java.util.logging: Tests that require java.util.logging code changes to fix.",
-  bug: 13882147,
-  names: [
-    "com.android.org.apache.harmony.logging.tests.java.util.logging.SocketHandlerTest#testConstructor_NoProperties",
-    "com.android.org.apache.harmony.logging.tests.java.util.logging.XMLFormatterTest#test_TestFileHandlerClass_constructor"
-  ]
-},
-{
   description: "java.util.beans: the harmony tests were broken by Android commit 19a270e90b1e992c1f6639f355ae13564c2f3a6a",
   bug: 17394106,
   names: [
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/EnumMapTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/EnumMapTest.java
index 2a37a18..676e373 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/EnumMapTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/EnumMapTest.java
@@ -233,6 +233,17 @@
         }
     }
 
+    @SuppressWarnings("unchecked")
+    public void testConstructor_badMapArg() {
+        HashMap badMap = new HashMap();
+        badMap.put("NotAnEnum", "Value");
+        try {
+            new EnumMap<Color, String>(badMap);
+            fail();
+        } catch (ClassCastException expected) {
+        }
+    }
+
     /**
      * java.util.EnumMap#clear()
      */
diff --git a/libart/src/main/java/dalvik/system/VMRuntime.java b/libart/src/main/java/dalvik/system/VMRuntime.java
index 43fa00e..f778af0 100644
--- a/libart/src/main/java/dalvik/system/VMRuntime.java
+++ b/libart/src/main/java/dalvik/system/VMRuntime.java
@@ -33,6 +33,10 @@
      */
     private static final VMRuntime THE_ONE = new VMRuntime();
 
+    // Note: Instruction set names are used to construct the names of some
+    // system properties. To be sure that the properties stay valid the
+    // instruction set name should not exceed 7 characters. See installd
+    // and the package manager for the actual propeties.
     private static final Map<String, String> ABI_TO_INSTRUCTION_SET_MAP
             = new HashMap<String, String>();
     static {
diff --git a/libart/src/main/java/java/lang/Class.java b/libart/src/main/java/java/lang/Class.java
index c66b01a..c004fa0 100644
--- a/libart/src/main/java/java/lang/Class.java
+++ b/libart/src/main/java/java/lang/Class.java
@@ -232,15 +232,15 @@
      */
     private transient int objectSize;
 
-    /** Primitive type value, or 0 if not a primitive type; set for generated primitive classes. */
+    /**
+     * The lower 16 bits is the primitive type value, or 0 if not a primitive type; set for
+     * generated primitive classes.
+     */
     private transient int primitiveType;
 
     /** Bitmap of offsets of iFields. */
     private transient int referenceInstanceOffsets;
 
-    /** Bitmap of offsets of sFields. */
-    private transient int referenceStaticOffsets;
-
     /** State of class initialization */
     private transient int status;
 
@@ -1513,7 +1513,7 @@
      * Tests whether this {@code Class} represents a primitive type.
      */
     public boolean isPrimitive() {
-      return primitiveType != 0;
+      return (primitiveType & 0xFFFF) != 0;
     }
 
     /**
diff --git a/libart/src/main/java/java/lang/reflect/ArtMethod.java b/libart/src/main/java/java/lang/reflect/ArtMethod.java
index 6d21f59..8ce158a 100644
--- a/libart/src/main/java/java/lang/reflect/ArtMethod.java
+++ b/libart/src/main/java/java/lang/reflect/ArtMethod.java
@@ -70,9 +70,8 @@
     /**
      * Method dispatch from portable compiled code invokes this pointer which may cause bridging
      * into quick compiled code or the interpreter.
-     * Uncomment to enable.
      */
-    // private long entryPointFromPortableCompiledCode;
+    private long entryPointFromPortableCompiledCode;
 
     /**
      * Method dispatch from quick compiled code invokes this pointer which may cause bridging
diff --git a/luni/src/main/java/java/io/ObjectStreamField.java b/luni/src/main/java/java/io/ObjectStreamField.java
index 78a6903..2a9b107 100644
--- a/luni/src/main/java/java/io/ObjectStreamField.java
+++ b/luni/src/main/java/java/io/ObjectStreamField.java
@@ -58,13 +58,7 @@
      *             if {@code name} or {@code cl} is {@code null}.
      */
     public ObjectStreamField(String name, Class<?> cl) {
-        if (name == null) {
-            throw new NullPointerException("name == null");
-        } else if (cl == null) {
-            throw new NullPointerException("cl == null");
-        }
-        this.name = name;
-        this.type = new WeakReference<Class<?>>(cl);
+        this(name, cl, false);
     }
 
     /**
diff --git a/luni/src/main/java/java/lang/StrictMath.java b/luni/src/main/java/java/lang/StrictMath.java
index f409c06..2e848f2 100644
--- a/luni/src/main/java/java/lang/StrictMath.java
+++ b/luni/src/main/java/java/lang/StrictMath.java
@@ -15,6 +15,18 @@
  *  limitations under the License.
  */
 
+/*
+ * acos, asin, atan, cosh, sinh, tanh, exp, expm1, log, log10, log1p, and cbrt
+ * have been implemented with the following license.
+ * ====================================================
+ * Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
 package java.lang;
 
 /**
@@ -102,6 +114,21 @@
         return Math.abs(l);
     }
 
+    private static final double PIO2_HI = 1.57079632679489655800e+00;
+    private static final double PIO2_LO = 6.12323399573676603587e-17;
+    private static final double PS0 = 1.66666666666666657415e-01;
+    private static final double PS1 = -3.25565818622400915405e-01;
+    private static final double PS2 = 2.01212532134862925881e-01;
+    private static final double PS3 = -4.00555345006794114027e-02;
+    private static final double PS4 = 7.91534994289814532176e-04;
+    private static final double PS5 = 3.47933107596021167570e-05;
+    private static final double QS1 = -2.40339491173441421878e+00;
+    private static final double QS2 = 2.02094576023350569471e+00;
+    private static final double QS3 = -6.88283971605453293030e-01;
+    private static final double QS4 = 7.70381505559019352791e-02;
+    private static final double HUGE = 1.000e+300;
+    private static final double PIO4_HI = 7.85398163397448278999e-01;
+
     /**
      * Returns the closest double approximation of the arc cosine of the
      * argument within the range {@code [0..pi]}.
@@ -113,11 +140,62 @@
      * <li>{@code acos(NaN) = NaN}</li>
      * </ul>
      *
-     * @param d
+     * @param x
      *            the value to compute arc cosine of.
      * @return the arc cosine of the argument.
      */
-    public static native double acos(double d);
+    public static double acos(double x) {
+        double z, p, q, r, w, s, c, df;
+        int hx, ix;
+        final long bits = Double.doubleToRawLongBits(x);
+        hx = (int) (bits >>> 32);
+        ix = hx & 0x7fffffff;
+        if (ix >= 0x3ff00000) { /* |x| >= 1 */
+            if ((((ix - 0x3ff00000) | ((int) bits))) == 0) { /* |x|==1 */
+                if (hx > 0) {
+                    return 0.0; /* ieee_acos(1) = 0 */
+                } else {
+                    return 3.14159265358979311600e+00 + 2.0 * PIO2_LO; /* ieee_acos(-1)= pi */
+                }
+            }
+            return (x - x) / (x - x); /* ieee_acos(|x|>1) is NaN */
+        }
+
+        if (ix < 0x3fe00000) { /* |x| < 0.5 */
+            if (ix <= 0x3c600000) {
+                return PIO2_HI + PIO2_LO;/* if|x|<2**-57 */
+            }
+
+            z = x * x;
+            p = z * (PS0 + z
+                    * (PS1 + z * (PS2 + z * (PS3 + z * (PS4 + z * PS5)))));
+            q = 1.00000000000000000000e+00 + z * (QS1 + z * (QS2 + z * (QS3 + z * QS4)));
+            r = p / q;
+            return PIO2_HI - (x - (PIO2_LO - x * r));
+        } else if (hx < 0) { /* x < -0.5 */
+            z = (1.00000000000000000000e+00 + x) * 0.5;
+            p = z * (PS0 + z
+                    * (PS1 + z * (PS2 + z * (PS3 + z * (PS4 + z * PS5)))));
+            q = 1.00000000000000000000e+00 + z * (QS1 + z * (QS2 + z * (QS3 + z * QS4)));
+            s = StrictMath.sqrt(z);
+            r = p / q;
+            w = r * s - PIO2_LO;
+            return 3.14159265358979311600e+00 - 2.0 * (s + w);
+        } else { /* x > 0.5 */
+            z = (1.00000000000000000000e+00 - x) * 0.5;
+            s = StrictMath.sqrt(z);
+            df = s;
+            df = Double.longBitsToDouble(
+                    Double.doubleToRawLongBits(df) & 0xffffffffL << 32);
+            c = (z - df * df) / (s + df);
+            p = z * (PS0 + z
+                    * (PS1 + z * (PS2 + z * (PS3 + z * (PS4 + z * PS5)))));
+            q = 1.00000000000000000000e+00 + z * (QS1 + z * (QS2 + z * (QS3 + z * QS4)));
+            r = p / q;
+            w = r * s + c;
+            return 2.0 * (df + w);
+        }
+    }
 
     /**
      * Returns the closest double approximation of the arc sine of the argument
@@ -130,11 +208,75 @@
      * <li>{@code asin(NaN) = NaN}</li>
      * </ul>
      *
-     * @param d
+     * @param x
      *            the value whose arc sine has to be computed.
      * @return the arc sine of the argument.
      */
-    public static native double asin(double d);
+    public static double asin(double x) {
+        double t, w, p, q, c, r, s;
+        int hx, ix;
+        final long bits = Double.doubleToRawLongBits(x);
+        hx = (int) (bits >>> 32);
+        ix = hx & 0x7fffffff;
+        if (ix >= 0x3ff00000) { /* |x|>= 1 */
+            if ((((ix - 0x3ff00000) | ((int) bits))) == 0) {
+                /* ieee_asin(1)=+-pi/2 with inexact */
+                return x * PIO2_HI + x * PIO2_LO;
+            }
+            return (x - x) / (x - x); /* ieee_asin(|x|>1) is NaN */
+        } else if (ix < 0x3fe00000) { /* |x|<0.5 */
+            if (ix < 0x3e400000) { /* if |x| < 2**-27 */
+                if (HUGE + x > 1.00000000000000000000e+00) {
+                    return x;/* return x with inexact if x!=0 */
+                }
+            } else {
+                t = x * x;
+                p = t * (PS0 + t
+                        * (PS1 + t * (PS2 + t * (PS3 + t * (PS4 + t * PS5)))));
+                q = 1.00000000000000000000e+00 + t * (QS1 + t * (QS2 + t * (QS3 + t * QS4)));
+                w = p / q;
+                return x + x * w;
+            }
+        }
+        /* 1> |x|>= 0.5 */
+        w = 1.00000000000000000000e+00 - Math.abs(x);
+        t = w * 0.5;
+        p = t * (PS0 + t * (PS1 + t * (PS2 + t * (PS3 + t * (PS4 + t * PS5)))));
+        q = 1.00000000000000000000e+00 + t * (QS1 + t * (QS2 + t * (QS3 + t * QS4)));
+        s = StrictMath.sqrt(t);
+        if (ix >= 0x3FEF3333) { /* if |x| > 0.975 */
+            w = p / q;
+            t = PIO2_HI - (2.0 * (s + s * w) - PIO2_LO);
+        } else {
+            w = s;
+            w = Double.longBitsToDouble(
+                    Double.doubleToRawLongBits(w) & 0xffffffffL << 32);
+            c = (t - w * w) / (s + w);
+            r = p / q;
+            p = 2.0 * s * r - (PIO2_LO - 2.0 * c);
+            q = PIO4_HI - 2.0 * w;
+            t = PIO4_HI - (p - q);
+        }
+        return (hx > 0) ? t : -t;
+    }
+
+    private static final double[] ATANHI = { 4.63647609000806093515e-01,
+            7.85398163397448278999e-01, 9.82793723247329054082e-01,
+            1.57079632679489655800e+00 };
+    private static final double[] ATANLO = { 2.26987774529616870924e-17,
+            3.06161699786838301793e-17, 1.39033110312309984516e-17,
+            6.12323399573676603587e-17 };
+    private static final double AT0 = 3.33333333333329318027e-01;
+    private static final double AT1 = -1.99999999998764832476e-01;
+    private static final double AT2 = 1.42857142725034663711e-01;
+    private static final double AT3 = -1.11111104054623557880e-01;
+    private static final double AT4 = 9.09088713343650656196e-02;
+    private static final double AT5 = -7.69187620504482999495e-02;
+    private static final double AT6 = 6.66107313738753120669e-02;
+    private static final double AT7= -5.83357013379057348645e-02;
+    private static final double AT8 = 4.97687799461593236017e-02;
+    private static final double AT9 = -3.65315727442169155270e-02;
+    private static final double AT10 = 1.62858201153657823623e-02;
 
     /**
      * Returns the closest double approximation of the arc tangent of the
@@ -149,11 +291,73 @@
      * <li>{@code atan(NaN) = NaN}</li>
      * </ul>
      *
-     * @param d
+     * @param x
      *            the value whose arc tangent has to be computed.
      * @return the arc tangent of the argument.
      */
-    public static native double atan(double d);
+    public static double atan(double x) {
+       double w, s1, s2, z;
+        int ix, hx, id;
+
+        final long bits = Double.doubleToRawLongBits(x);
+        hx = (int) (bits >>> 32);
+        ix = hx & 0x7fffffff;
+        if (ix >= 0x44100000) { /* if |x| >= 2^66 */
+            if (ix > 0x7ff00000 || (ix == 0x7ff00000 && (((int) bits) != 0))) {
+                return x + x; /* NaN */
+            }
+            if (hx > 0) {
+                return ATANHI[3] + ATANLO[3];
+            } else {
+                return -ATANHI[3] - ATANLO[3];
+            }
+        }
+        if (ix < 0x3fdc0000) { /* |x| < 0.4375 */
+            if (ix < 0x3e200000) { /* |x| < 2^-29 */
+                if (HUGE + x > 1.00000000000000000000e+00) {
+                    return x; /* raise inexact */
+                }
+            }
+            id = -1;
+        } else {
+            x = Math.abs(x);
+            if (ix < 0x3ff30000) { /* |x| < 1.1875 */
+                if (ix < 0x3fe60000) { /* 7/16 <=|x|<11/16 */
+                    id = 0;
+                    x = (2.0 * x - 1.00000000000000000000e+00) / (2.0 + x);
+                } else { /* 11/16<=|x|< 19/16 */
+                    id = 1;
+                    x = (x - 1.00000000000000000000e+00) / (x + 1.00000000000000000000e+00);
+                }
+            } else {
+                if (ix < 0x40038000) { /* |x| < 2.4375 */
+                    id = 2;
+                    x = (x - 1.5) / (1.00000000000000000000e+00 + 1.5 * x);
+                } else { /* 2.4375 <= |x| < 2^66 */
+                    id = 3;
+                    x = -1.0 / x;
+                }
+            }
+        }
+
+        /* end of argument reduction */
+        z = x * x;
+        w = z * z;
+        /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */
+        s1 = z * (AT0 + w * (AT2 + w
+                * (AT4 + w * (AT6 + w * (AT8 + w * AT10)))));
+        s2 = w * (AT1 + w * (AT3 + w * (AT5 + w * (AT7 + w * AT9))));
+        if (id < 0) {
+            return x - x * (s1 + s2);
+        } else {
+            z = ATANHI[id] - ((x * (s1 + s2) - ATANLO[id]) - x);
+            return (hx < 0) ? -z : z;
+        }
+    }
+
+    private static final double PI_O_4 = 7.8539816339744827900E-01;
+    private static final double PI_O_2 = 1.5707963267948965580E+00;
+    private static final double PI_LO = 1.2246467991473531772E-16;
 
     /**
      * Returns the closest double approximation of the arc tangent of
@@ -192,7 +396,108 @@
      *            the denominator of the value whose atan has to be computed.
      * @return the arc tangent of {@code y/x}.
      */
-    public static native double atan2(double y, double x);
+    public static double atan2(double y, double x) {
+        double z;
+        int k, m, hx, hy, ix, iy;
+        int lx, ly; // watch out, should be unsigned
+
+        final long yBits = Double.doubleToRawLongBits(y);
+        final long xBits = Double.doubleToRawLongBits(x);
+
+        hx = (int) (xBits >>> 32); // __HI(x);
+        ix = hx & 0x7fffffff;
+        lx = (int) xBits; // __LO(x);
+        hy = (int) (yBits >>> 32); // __HI(y);
+        iy = hy & 0x7fffffff;
+        ly = (int) yBits; // __LO(y);
+        if (((ix | ((lx | -lx) >> 31)) > 0x7ff00000)
+                || ((iy | ((ly | -ly) >> 31)) > 0x7ff00000)) { /* x or y is NaN */
+            return x + y;
+        }
+        if ((hx - 0x3ff00000 | lx) == 0) {
+            return StrictMath.atan(y); /* x=1.0 */
+        }
+
+        m = ((hy >> 31) & 1) | ((hx >> 30) & 2); /* 2*sign(x)+sign(y) */
+
+        /* when y = 0 */
+        if ((iy | ly) == 0) {
+            switch (m) {
+                case 0:
+                case 1:
+                    return y; /* ieee_atan(+-0,+anything)=+-0 */
+                case 2:
+                    return 3.14159265358979311600e+00 + TINY;/* ieee_atan(+0,-anything) = pi */
+                case 3:
+                    return -3.14159265358979311600e+00 - TINY;/* ieee_atan(-0,-anything) =-pi */
+            }
+        }
+        /* when x = 0 */
+        if ((ix | lx) == 0)
+            return (hy < 0) ? -PI_O_2 - TINY : PI_O_2 + TINY;
+
+        /* when x is INF */
+        if (ix == 0x7ff00000) {
+            if (iy == 0x7ff00000) {
+                switch (m) {
+                    case 0:
+                        return PI_O_4 + TINY;/* ieee_atan(+INF,+INF) */
+                    case 1:
+                        return -PI_O_4 - TINY;/* ieee_atan(-INF,+INF) */
+                    case 2:
+                        return 3.0 * PI_O_4 + TINY;/* ieee_atan(+INF,-INF) */
+                    case 3:
+                        return -3.0 * PI_O_4 - TINY;/* ieee_atan(-INF,-INF) */
+                }
+            } else {
+                switch (m) {
+                    case 0:
+                        return 0.0; /* ieee_atan(+...,+INF) */
+                    case 1:
+                        return -0.0; /* ieee_atan(-...,+INF) */
+                    case 2:
+                        return 3.14159265358979311600e+00 + TINY; /* ieee_atan(+...,-INF) */
+                    case 3:
+                        return -3.14159265358979311600e+00 - TINY; /* ieee_atan(-...,-INF) */
+                }
+            }
+        }
+        /* when y is INF */
+        if (iy == 0x7ff00000)
+            return (hy < 0) ? -PI_O_2 - TINY : PI_O_2 + TINY;
+
+        /* compute y/x */
+        k = (iy - ix) >> 20;
+        if (k > 60) {
+            z = PI_O_2 + 0.5 * PI_LO; /* |y/x| > 2**60 */
+        } else if (hx < 0 && k < -60) {
+            z = 0.0; /* |y|/x < -2**60 */
+        } else {
+            z = StrictMath.atan(Math.abs(y / x)); /* safe to do y/x */
+        }
+
+        switch (m) {
+            case 0:
+                return z; /* ieee_atan(+,+) */
+            case 1:
+                // __HI(z) ^= 0x80000000;
+                z = Double.longBitsToDouble(
+                        Double.doubleToRawLongBits(z) ^ (0x80000000L << 32));
+                return z; /* ieee_atan(-,+) */
+            case 2:
+                return 3.14159265358979311600e+00 - (z - PI_LO);/* ieee_atan(+,-) */
+            default: /* case 3 */
+                return (z - PI_LO) - 3.14159265358979311600e+00;/* ieee_atan(-,-) */
+        }
+    }
+
+    private static final int B1 = 715094163;
+    private static final int B2 = 696219795;
+    private static final double C = 5.42857142857142815906e-01;
+    private static final double D = -7.05306122448979611050e-01;
+    private static final double CBRTE = 1.41428571428571436819e+00;
+    private static final double F = 1.60714285714285720630e+00;
+    private static final double G = 3.57142857142857150787e-01;
 
     /**
      * Returns the closest double approximation of the cube root of the
@@ -207,11 +512,79 @@
      * <li>{@code cbrt(NaN) = NaN}</li>
      * </ul>
      *
-     * @param d
+     * @param x
      *            the value whose cube root has to be computed.
      * @return the cube root of the argument.
      */
-    public static native double cbrt(double d);
+    public static double cbrt(double x) {
+        if (x < 0) {
+            return -cbrt(-x);
+        }
+        int hx;
+        double r, s, w;
+        int sign; // caution: should be unsigned
+        long bits = Double.doubleToRawLongBits(x);
+
+        hx = (int) (bits >>> 32);
+        sign = hx & 0x80000000; /* sign= sign(x) */
+        hx ^= sign;
+        if (hx >= 0x7ff00000) {
+            return (x + x); /* ieee_cbrt(NaN,INF) is itself */
+        }
+
+        if ((hx | ((int) bits)) == 0) {
+            return x; /* ieee_cbrt(0) is itself */
+        }
+
+        // __HI(x) = hx; /* x <- |x| */
+        bits &= 0x00000000ffffffffL;
+        bits |= ((long) hx << 32);
+
+        long tBits = Double.doubleToRawLongBits(0.0) & 0x00000000ffffffffL;
+        double t = 0.0;
+        /* rough cbrt to 5 bits */
+        if (hx < 0x00100000) { /* subnormal number */
+            // __HI(t)=0x43500000; /*set t= 2**54*/
+            tBits |= 0x43500000L << 32;
+            t = Double.longBitsToDouble(tBits);
+            t *= x;
+
+            // __HI(t)=__HI(t)/3+B2;
+            tBits = Double.doubleToRawLongBits(t);
+            long tBitsHigh = tBits >> 32;
+            tBits &= 0x00000000ffffffffL;
+            tBits |= ((tBitsHigh / 3) + B2) << 32;
+            t = Double.longBitsToDouble(tBits);
+
+        } else {
+            // __HI(t)=hx/3+B1;
+            tBits |= ((long) ((hx / 3) + B1)) << 32;
+            t = Double.longBitsToDouble(tBits);
+        }
+
+        /* new cbrt to 23 bits, may be implemented in single precision */
+        r = t * t / x;
+        s = C + r * t;
+        t *= G + F / (s + CBRTE + D / s);
+
+        /* chopped to 20 bits and make it larger than ieee_cbrt(x) */
+        tBits = Double.doubleToRawLongBits(t);
+        tBits &= 0xFFFFFFFFL << 32;
+        tBits += 0x00000001L << 32;
+        t = Double.longBitsToDouble(tBits);
+
+        /* one step newton iteration to 53 bits with error less than 0.667 ulps */
+        s = t * t; /* t*t is exact */
+        r = x / s;
+        w = t + t;
+        r = (r - t) / (w + r); /* r-s is exact */
+        t = t + t * r;
+
+        /* retore the sign bit */
+        tBits = Double.doubleToRawLongBits(t);
+        tBits |= ((long) sign) << 32;
+        return Double.longBitsToDouble(tBits);
+    }
 
     /**
      * Returns the double conversion of the most negative (closest to negative
@@ -229,6 +602,8 @@
      */
     public static native double ceil(double d);
 
+    private static final long ONEBITS = Double.doubleToRawLongBits(1.00000000000000000000e+00)
+            & 0x00000000ffffffffL;
 
     /**
      * Returns the closest double approximation of the hyperbolic cosine of the
@@ -241,11 +616,54 @@
      * <li>{@code cosh(NaN) = NaN}</li>
      * </ul>
      *
-     * @param d
+     * @param x
      *            the value whose hyperbolic cosine has to be computed.
      * @return the hyperbolic cosine of the argument.
      */
-    public static native double cosh(double d);
+    public static double cosh(double x) {
+        double t, w;
+        int ix;
+        final long bits = Double.doubleToRawLongBits(x);
+        ix = (int) (bits >>> 32) & 0x7fffffff;
+
+        /* x is INF or NaN */
+        if (ix >= 0x7ff00000) {
+            return x * x;
+        }
+
+        /* |x| in [0,0.5*ln2], return 1+ieee_expm1(|x|)^2/(2*ieee_exp(|x|)) */
+        if (ix < 0x3fd62e43) {
+            t = expm1(Math.abs(x));
+            w = 1.00000000000000000000e+00 + t;
+            if (ix < 0x3c800000)
+                return w; /* ieee_cosh(tiny) = 1 */
+            return 1.00000000000000000000e+00 + (t * t) / (w + w);
+        }
+
+        /* |x| in [0.5*ln2,22], return (ieee_exp(|x|)+1/ieee_exp(|x|)/2; */
+        if (ix < 0x40360000) {
+            t = exp(Math.abs(x));
+            return 0.5 * t + 0.5 / t;
+        }
+
+        /* |x| in [22, ieee_log(maxdouble)] return half*ieee_exp(|x|) */
+        if (ix < 0x40862E42) {
+            return 0.5 * exp(Math.abs(x));
+        }
+
+        /* |x| in [log(maxdouble), overflowthresold] */
+        final long lx = ((ONEBITS >>> 29) + ((int) bits)) & 0x00000000ffffffffL;
+        // watch out: lx should be an unsigned int
+        // lx = *( (((*(unsigned*)&one)>>29)) + (unsigned*)&x);
+        if (ix < 0x408633CE || (ix == 0x408633ce) && (lx <= 0x8fb9f87dL)) {
+            w = exp(0.5 * Math.abs(x));
+            t = 0.5 * w;
+            return t * w;
+        }
+
+        /* |x| > overflowthresold, ieee_cosh(x) overflow */
+        return HUGE * HUGE;
+    }
 
     /**
      * Returns the closest double approximation of the cosine of the argument.
@@ -263,6 +681,19 @@
      */
     public static native double cos(double d);
 
+    private static final double TWON24 = 5.96046447753906250000e-08;
+    private static final double TWO54 = 1.80143985094819840000e+16,
+            TWOM54 = 5.55111512312578270212e-17;
+    private static final double TWOM1000 = 9.33263618503218878990e-302;
+    private static final double O_THRESHOLD = 7.09782712893383973096e+02;
+    private static final double U_THRESHOLD = -7.45133219101941108420e+02;
+    private static final double INVLN2 = 1.44269504088896338700e+00;
+    private static final double P1 = 1.66666666666666019037e-01;
+    private static final double P2 = -2.77777777770155933842e-03;
+    private static final double P3 = 6.61375632143793436117e-05;
+    private static final double P4 = -1.65339022054652515390e-06;
+    private static final double P5 = 4.13813679705723846039e-08;
+
     /**
      * Returns the closest double approximation of the raising "e" to the power
      * of the argument.
@@ -274,11 +705,88 @@
      * <li>{@code exp(NaN) = NaN}</li>
      * </ul>
      *
-     * @param d
+     * @param x
      *            the value whose exponential has to be computed.
      * @return the exponential of the argument.
      */
-    public static native double exp(double d);
+    public static double exp(double x) {
+        double y, c, t;
+        double hi = 0, lo = 0;
+        int k = 0, xsb;
+        int hx; // should be unsigned, be careful!
+        final long bits = Double.doubleToRawLongBits(x);
+        int lowBits = (int) bits;
+        int highBits = (int) (bits >>> 32);
+        hx = highBits & 0x7fffffff;
+        xsb = (highBits >>> 31) & 1;
+
+        /* filter out non-finite argument */
+        if (hx >= 0x40862E42) { /* if |x|>=709.78... */
+            if (hx >= 0x7ff00000) {
+                if (((hx & 0xfffff) | lowBits) != 0) {
+                    return x + x; /* NaN */
+                } else {
+                    return (xsb == 0) ? x : 0.0; /* ieee_exp(+-inf)={inf,0} */
+                }
+            }
+
+            if (x > O_THRESHOLD) {
+                return HUGE * HUGE; /* overflow */
+            }
+
+            if (x < U_THRESHOLD) {
+                return TWOM1000 * TWOM1000; /* underflow */
+            }
+        }
+
+        /* argument reduction */
+        if (hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */
+            if (hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */
+                hi = x - ((xsb == 0) ? 6.93147180369123816490e-01 :
+                        -6.93147180369123816490e-01); // LN2HI[xsb];
+                lo = (xsb == 0) ? 1.90821492927058770002e-10 :
+                        -1.90821492927058770002e-10; // LN2LO[xsb];
+                k = 1 - xsb - xsb;
+            } else {
+                k = (int) (INVLN2 * x + ((xsb == 0) ? 0.5 : -0.5 ));//halF[xsb]);
+                t = k;
+                hi = x - t * 6.93147180369123816490e-01; //ln2HI[0]; /* t*ln2HI is exact here */
+                lo = t * 1.90821492927058770002e-10; //ln2LO[0];
+            }
+            x = hi - lo;
+        } else if (hx < 0x3e300000) { /* when |x|<2**-28 */
+            if (HUGE + x > 1.00000000000000000000e+00)
+                return 1.00000000000000000000e+00 + x;/* trigger inexact */
+        } else {
+            k = 0;
+        }
+
+        /* x is now in primary range */
+        t = x * x;
+        c = x - t * (P1 + t * (P2 + t * (P3 + t * (P4 + t * P5))));
+        if (k == 0) {
+            return 1.00000000000000000000e+00 - ((x * c) / (c - 2.0) - x);
+        } else {
+            y = 1.00000000000000000000e+00 - ((lo - (x * c) / (2.0 - c)) - hi);
+        }
+        long yBits = Double.doubleToRawLongBits(y);
+        if (k >= -1021) {
+            yBits += ((long) (k << 20)) << 32; /* add k to y's exponent */
+            return Double.longBitsToDouble(yBits);
+        } else {
+            yBits += ((long) ((k + 1000) << 20)) << 32;/* add k to y's exponent */
+            return Double.longBitsToDouble(yBits) * TWOM1000;
+        }
+    }
+
+    private static final double TINY = 1.0e-300;
+    private static final double LN2_HI = 6.93147180369123816490e-01;
+    private static final double LN2_LO = 1.90821492927058770002e-10;
+    private static final double Q1 = -3.33333333333331316428e-02;
+    private static final double Q2 = 1.58730158725481460165e-03;
+    private static final double Q3 = -7.93650757867487942473e-05;
+    private static final double Q4 = 4.00821782732936239552e-06;
+    private static final double Q5 = -2.01099218183624371326e-07;
 
     /**
      * Returns the closest double approximation of <i>{@code e}</i><sup>
@@ -295,17 +803,124 @@
      * <li>{@code expm1(NaN) = NaN}</li>
      * </ul>
      *
-     * @param d
+     * @param x
      *            the value to compute the <i>{@code e}</i><sup>{@code d}</sup>
      *            {@code - 1} of.
-     * @return the <i>{@code e}</i><sup>{@code d}</sup>{@code - 1} value
-     *         of the argument.
+     * @return the <i>{@code e}</i><sup>{@code d}</sup>{@code - 1} value of the
+     *         argument.
      */
-    public static native double expm1(double d);
+    public static double expm1(double x) {
+        double y, hi, lo, t, e, hxs, hfx, r1, c = 0.0;
+        int k, xsb;
+        long yBits = 0;
+        final long bits = Double.doubleToRawLongBits(x);
+        int highBits = (int) (bits >>> 32);
+        int lowBits = (int) (bits);
+        int hx = highBits & 0x7fffffff; // caution: should be unsigned!
+        xsb = highBits & 0x80000000; /* sign bit of x */
+        y = xsb == 0 ? x : -x; /* y = |x| */
+
+        /* filter out huge and non-finite argument */
+        if (hx >= 0x4043687A) { /* if |x|>=56*ln2 */
+            if (hx >= 0x40862E42) { /* if |x|>=709.78... */
+                if (hx >= 0x7ff00000) {
+                    if (((hx & 0xfffff) | lowBits) != 0) {
+                        return x + x; /* NaN */
+                    } else {
+                        return (xsb == 0) ? x : -1.0;/* ieee_exp(+-inf)={inf,-1} */
+                    }
+                }
+                if (x > O_THRESHOLD) {
+                    return HUGE * HUGE; /* overflow */
+                }
+            }
+            if (xsb != 0) { /* x < -56*ln2, return -1.0 with inexact */
+                if (x + TINY < 0.0) { /* raise inexact */
+                    return TINY - 1.00000000000000000000e+00; /* return -1 */
+                }
+            }
+        }
+        /* argument reduction */
+        if (hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */
+            if (hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */
+                if (xsb == 0) {
+                    hi = x - LN2_HI;
+                    lo = LN2_LO;
+                    k = 1;
+                } else {
+                    hi = x + LN2_HI;
+                    lo = -LN2_LO;
+                    k = -1;
+                }
+            } else {
+                k = (int) (INVLN2 * x + ((xsb == 0) ? 0.5 : -0.5));
+                t = k;
+                hi = x - t * LN2_HI; /* t*ln2_hi is exact here */
+                lo = t * LN2_LO;
+            }
+            x = hi - lo;
+            c = (hi - x) - lo;
+        } else if (hx < 0x3c900000) { /* when |x|<2**-54, return x */
+            // t = huge+x; /* return x with inexact flags when x!=0 */
+            // return x - (t-(huge+x));
+            return x; // inexact flag is not set, but Java ignors this flag
+                      // anyway
+        } else {
+            k = 0;
+        }
+
+        /* x is now in primary range */
+        hfx = 0.5 * x;
+        hxs = x * hfx;
+        r1 = 1.00000000000000000000e+00 + hxs * (Q1 + hxs * (Q2 + hxs * (Q3 + hxs * (Q4 + hxs * Q5))));
+        t = 3.0 - r1 * hfx;
+        e = hxs * ((r1 - t) / (6.0 - x * t));
+        if (k == 0) {
+            return x - (x * e - hxs); /* c is 0 */
+        } else {
+            e = (x * (e - c) - c);
+            e -= hxs;
+            if (k == -1) {
+                return 0.5 * (x - e) - 0.5;
+            }
+
+            if (k == 1) {
+                if (x < -0.25) {
+                    return -2.0 * (e - (x + 0.5));
+                } else {
+                    return 1.00000000000000000000e+00 + 2.0 * (x - e);
+                }
+            }
+
+            if (k <= -2 || k > 56) { /* suffice to return ieee_exp(x)-1 */
+                y = 1.00000000000000000000e+00 - (e - x);
+                yBits = Double.doubleToRawLongBits(y);
+                yBits += (((long) k) << 52); /* add k to y's exponent */
+                return Double.longBitsToDouble(yBits) - 1.00000000000000000000e+00;
+            }
+
+            long tBits = Double.doubleToRawLongBits(1.00000000000000000000e+00) & 0x00000000ffffffffL;
+
+            if (k < 20) {
+                tBits |= (((long) 0x3ff00000) - (0x200000 >> k)) << 32;
+                y = Double.longBitsToDouble(tBits) - (e - x);
+                yBits = Double.doubleToRawLongBits(y);
+                yBits += (((long) k) << 52); /* add k to y's exponent */
+                return Double.longBitsToDouble(yBits);
+            } else {
+                tBits |= ((((long) 0x3ff) - k) << 52); /* 2^-k */
+                y = x - (e + Double.longBitsToDouble(tBits));
+                y += 1.00000000000000000000e+00;
+                yBits = Double.doubleToRawLongBits(y);
+                yBits += (((long) k) << 52); /* add k to y's exponent */
+                return Double.longBitsToDouble(yBits);
+            }
+        }
+    }
 
     /**
-     * Returns the double conversion of the most positive (closest to
-     * positive infinity) integer less than or equal to the argument.
+     * Returns the double conversion of the most positive (closest to positive
+     * infinity) integer less than or equal to the argument.
      * <p>
      * Special cases:
      * <ul>
@@ -319,9 +934,9 @@
     public static native double floor(double d);
 
     /**
-     * Returns {@code sqrt(}<i>{@code x}</i><sup>{@code 2}</sup>{@code +}
-     * <i> {@code y}</i><sup>{@code 2}</sup>{@code )}. The final result is
-     * without medium underflow or overflow.
+     * Returns {@code sqrt(}<i>{@code x}</i><sup>{@code 2}</sup>{@code +} <i>
+     * {@code y}</i><sup>{@code 2}</sup>{@code )}. The final result is without
+     * medium underflow or overflow.
      * <p>
      * Special cases:
      * <ul>
@@ -369,6 +984,14 @@
      */
     public static native double IEEEremainder(double x, double y);
 
+    private static final double LG1 = 6.666666666666735130e-01;
+    private static final double LG2 = 3.999999999940941908e-01;
+    private static final double LG3 = 2.857142874366239149e-01;
+    private static final double LG4 = 2.222219843214978396e-01;
+    private static final double LG5 = 1.818357216161805012e-01;
+    private static final double LG6 = 1.531383769920937332e-01;
+    private static final double LG7 = 1.479819860511658591e-01;
+
     /**
      * Returns the closest double approximation of the natural logarithm of the
      * argument.
@@ -383,11 +1006,95 @@
      * <li>{@code log(NaN) = NaN}</li>
      * </ul>
      *
-     * @param d
+     * @param x
      *            the value whose log has to be computed.
      * @return the natural logarithm of the argument.
      */
-    public static native double log(double d);
+    public static double log(double x) {
+        double hfsq, f, s, z, R, w, t1, t2, dk;
+        int hx, i, j, k = 0;
+        int lx; // watch out, should be unsigned
+
+        long bits = Double.doubleToRawLongBits(x);
+        hx = (int) (bits >>> 32); /* high word of x */
+        lx = (int) bits; /* low word of x */
+
+        if (hx < 0x00100000) { /* x < 2**-1022 */
+            if (((hx & 0x7fffffff) | lx) == 0) {
+                return -TWO54 / 0.0; /* ieee_log(+-0)=-inf */
+            }
+
+            if (hx < 0) {
+                return (x - x) / 0.0; /* ieee_log(-#) = NaN */
+            }
+
+            k -= 54;
+            x *= TWO54; /* subnormal number, scale up x */
+            bits = Double.doubleToRawLongBits(x);
+            hx = (int) (bits >>> 32); /* high word of x */
+        }
+
+        if (hx >= 0x7ff00000) {
+            return x + x;
+        }
+
+        k += (hx >> 20) - 1023;
+        hx &= 0x000fffff;
+        bits &= 0x00000000ffffffffL;
+        i = (hx + 0x95f64) & 0x100000;
+        bits |= ((long) hx | (i ^ 0x3ff00000)) << 32; /* normalize x or x/2 */
+        x = Double.longBitsToDouble(bits);
+        k += (i >> 20);
+        f = x - 1.0;
+
+        if ((0x000fffff & (2 + hx)) < 3) { /* |f| < 2**-20 */
+            if (f == 0.0) {
+                if (k == 0) {
+                    return 0.0;
+                } else {
+                    dk = k;
+                }
+                return dk * LN2_HI + dk * LN2_LO;
+            }
+
+            R = f * f * (0.5 - 0.33333333333333333 * f);
+            if (k == 0) {
+                return f - R;
+            } else {
+                dk = k;
+                return dk * LN2_HI - ((R - dk * LN2_LO) - f);
+            }
+        }
+        s = f / (2.0 + f);
+        dk = k;
+        z = s * s;
+        i = hx - 0x6147a;
+        w = z * z;
+        j = 0x6b851 - hx;
+        t1 = w * (LG2 + w * (LG4 + w * LG6));
+        t2 = z * (LG1 + w * (LG3 + w * (LG5 + w * LG7)));
+        i |= j;
+        R = t2 + t1;
+        if (i > 0) {
+            hfsq = 0.5 * f * f;
+            if (k == 0) {
+                return f - (hfsq - s * (hfsq + R));
+            } else {
+                return dk * LN2_HI
+                        - ((hfsq - (s * (hfsq + R) + dk * LN2_LO)) - f);
+            }
+        } else {
+            if (k == 0) {
+                return f - s * (f - R);
+            } else {
+                return dk * LN2_HI - ((s * (f - R) - dk * LN2_LO) - f);
+            }
+        }
+    }
+
+    private static final double IVLN10 = 4.34294481903251816668e-01;
+    private static final double LOG10_2HI = 3.01029995663611771306e-01;
+    private static final double LOG10_2LO = 3.69423907715893078616e-13;
 
     /**
      * Returns the closest double approximation of the base 10 logarithm of the
@@ -403,11 +1110,54 @@
      * <li>{@code log10(NaN) = NaN}</li>
      * </ul>
      *
-     * @param d
+     * @param x
      *            the value whose base 10 log has to be computed.
-     * @return the natural logarithm of the argument.
+     * @return the the base 10 logarithm of x
      */
-    public static native double log10(double d);
+    public static double log10(double x) {
+        double y, z;
+        int i, k = 0, hx;
+        int lx; // careful: lx should be unsigned!
+        long bits = Double.doubleToRawLongBits(x);
+        hx = (int) (bits >> 32); /* high word of x */
+        lx = (int) bits; /* low word of x */
+        if (hx < 0x00100000) { /* x < 2**-1022 */
+            if (((hx & 0x7fffffff) | lx) == 0) {
+                return -TWO54 / 0.0; /* ieee_log(+-0)=-inf */
+            }
+
+            if (hx < 0) {
+                return (x - x) / 0.0; /* ieee_log(-#) = NaN */
+            }
+
+            k -= 54;
+            x *= TWO54; /* subnormal number, scale up x */
+            bits = Double.doubleToRawLongBits(x);
+            hx = (int) (bits >> 32); /* high word of x */
+        }
+
+        if (hx >= 0x7ff00000) {
+            return x + x;
+        }
+
+        k += (hx >> 20) - 1023;
+        i = (int) (((k & 0x00000000ffffffffL) & 0x80000000) >>> 31);
+        hx = (hx & 0x000fffff) | ((0x3ff - i) << 20);
+        y = k + i;
+        bits &= 0x00000000ffffffffL;
+        bits |= ((long) hx) << 32;
+        x = Double.longBitsToDouble(bits); // __HI(x) = hx;
+        z = y * LOG10_2LO + IVLN10 * log(x);
+        return z + y * LOG10_2HI;
+    }
+
+    private static final double LP1 = 6.666666666666735130e-01,
+            LP2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */
+            LP3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */
+            LP4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */
+            LP5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */
+            LP6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */
+            LP7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */
 
     /**
      * Returns the closest double approximation of the natural logarithm of the
@@ -426,11 +1176,107 @@
      * <li>{@code log1p(NaN) = NaN}</li>
      * </ul>
      *
-     * @param d
+     * @param x
      *            the value to compute the {@code ln(1+d)} of.
      * @return the natural logarithm of the sum of the argument and 1.
      */
-    public static native double log1p(double d);
+
+    public static double log1p(double x) {
+        double hfsq, f = 0.0, c = 0.0, s, z, R, u = 0.0;
+        int k, hx, hu = 0, ax;
+
+        final long bits = Double.doubleToRawLongBits(x);
+        hx = (int) (bits >>> 32); /* high word of x */
+        ax = hx & 0x7fffffff;
+
+        k = 1;
+        if (hx < 0x3FDA827A) { /* x < 0.41422 */
+            if (ax >= 0x3ff00000) { /* x <= -1.0 */
+                if (x == -1.0) {
+                    return -TWO54 / 0.0; /* ieee_log1p(-1)=+inf */
+                } else {
+                    return (x - x) / (x - x); /* ieee_log1p(x<-1)=NaN */
+                }
+            }
+            if (ax < 0x3e200000) {
+                if (TWO54 + x > 0.0 && ax < 0x3c900000) {
+                    return x;
+                } else {
+                    return x - x * x * 0.5;
+                }
+            }
+            if (hx > 0 || hx <= 0xbfd2bec3) {
+                k = 0;
+                f = x;
+                hu = 1;
+            } /* -0.2929<x<0.41422 */
+        }
+
+        if (hx >= 0x7ff00000) {
+            return x + x;
+        }
+
+        if (k != 0) {
+            long uBits;
+            if (hx < 0x43400000) {
+                u = 1.0 + x;
+                uBits = Double.doubleToRawLongBits(u);
+                hu = (int) (uBits >>> 32);
+                k = (hu >> 20) - 1023;
+                c = (k > 0) ? 1.0 - (u - x) : x - (u - 1.0);/* correction term */
+                c /= u;
+            } else {
+                uBits = Double.doubleToRawLongBits(x);
+                hu = (int) (uBits >>> 32);
+                k = (hu >> 20) - 1023;
+                c = 0;
+            }
+            hu &= 0x000fffff;
+            if (hu < 0x6a09e) {
+                // __HI(u) = hu|0x3ff00000; /* normalize u */
+                uBits &= 0x00000000ffffffffL;
+                uBits |= ((long) hu | 0x3ff00000) << 32;
+                u = Double.longBitsToDouble(uBits);
+            } else {
+                k += 1;
+                // __HI(u) = hu|0x3fe00000; /* normalize u/2 */
+                uBits &= 0xffffffffL;
+                uBits |= ((long) hu | 0x3fe00000) << 32;
+                u = Double.longBitsToDouble(uBits);
+                hu = (0x00100000 - hu) >> 2;
+            }
+            f = u - 1.0;
+        }
+        hfsq = 0.5 * f * f;
+        if (hu == 0) { /* |f| < 2**-20 */
+            if (f == 0.0) {
+                if (k == 0) {
+                    return 0.0;
+                } else {
+                    c += k * LN2_LO;
+                    return k * LN2_HI + c;
+                }
+            }
+
+            R = hfsq * (1.0 - 0.66666666666666666 * f);
+            if (k == 0) {
+                return f - R;
+            } else {
+                return k * LN2_HI - ((R - (k * LN2_LO + c)) - f);
+            }
+        }
+
+        s = f / (2.0 + f);
+        z = s * s;
+        R = z * (LP1 + z * (LP2 + z
+                * (LP3 + z * (LP4 + z * (LP5 + z * (LP6 + z * LP7))))));
+        if (k == 0) {
+            return f - (hfsq - s * (hfsq + R));
+        } else {
+            return k * LN2_HI
+                    - ((hfsq - (s * (hfsq + R) + (k * LN2_LO + c))) - f);
+        }
+    }
 
     /**
      * Returns the most positive (closest to positive infinity) of the two
@@ -453,8 +1299,8 @@
         if (d1 != d2)
             return Double.NaN;
         /* max( +0.0,-0.0) == +0.0 */
-        if (d1 == 0.0
-                && ((Double.doubleToLongBits(d1) & Double.doubleToLongBits(d2)) & 0x8000000000000000L) == 0)
+        if (d1 == 0.0 &&
+                ((Double.doubleToLongBits(d1) & Double.doubleToLongBits(d2)) & 0x8000000000000000L) == 0)
             return 0.0;
         return d1;
     }
@@ -480,8 +1326,8 @@
         if (f1 != f2)
             return Float.NaN;
         /* max( +0.0,-0.0) == +0.0 */
-        if (f1 == 0.0f
-                && ((Float.floatToIntBits(f1) & Float.floatToIntBits(f2)) & 0x80000000) == 0)
+        if (f1 == 0.0f &&
+                ((Float.floatToIntBits(f1) & Float.floatToIntBits(f2)) & 0x80000000) == 0)
             return 0.0f;
         return f1;
     }
@@ -523,8 +1369,8 @@
         if (d1 != d2)
             return Double.NaN;
         /* min( +0.0,-0.0) == -0.0 */
-        if (d1 == 0.0
-                && ((Double.doubleToLongBits(d1) | Double.doubleToLongBits(d2)) & 0x8000000000000000l) != 0)
+        if (d1 == 0.0 &&
+                ((Double.doubleToLongBits(d1) | Double.doubleToLongBits(d2)) & 0x8000000000000000l) != 0)
             return 0.0 * (-1.0);
         return d1;
     }
@@ -550,8 +1396,8 @@
         if (f1 != f2)
             return Float.NaN;
         /* min( +0.0,-0.0) == -0.0 */
-        if (f1 == 0.0f
-                && ((Float.floatToIntBits(f1) | Float.floatToIntBits(f2)) & 0x80000000) != 0)
+        if (f1 == 0.0f &&
+                ((Float.floatToIntBits(f1) | Float.floatToIntBits(f2)) & 0x80000000) != 0)
             return 0.0f * (-1.0f);
         return f1;
     }
@@ -706,7 +1552,7 @@
      *            the value whose signum has to be computed.
      * @return the value of the signum function.
      */
-    public static double signum(double d){
+    public static double signum(double d) {
         return Math.signum(d);
     }
 
@@ -729,10 +1575,12 @@
      *            the value whose signum has to be computed.
      * @return the value of the signum function.
      */
-    public static float signum(float f){
+    public static float signum(float f) {
         return Math.signum(f);
     }
 
+    private static final double shuge = 1.0e307;
+
     /**
      * Returns the closest double approximation of the hyperbolic sine of the
      * argument.
@@ -746,11 +1594,57 @@
      * <li>{@code sinh(NaN) = NaN}</li>
      * </ul>
      *
-     * @param d
+     * @param x
      *            the value whose hyperbolic sine has to be computed.
      * @return the hyperbolic sine of the argument.
      */
-    public static native double sinh(double d);
+    public static double sinh(double x) {
+        double t, w, h;
+        int ix, jx;
+        final long bits = Double.doubleToRawLongBits(x);
+
+        jx = (int) (bits >>> 32);
+        ix = jx & 0x7fffffff;
+
+        /* x is INF or NaN */
+        if (ix >= 0x7ff00000) {
+            return x + x;
+        }
+
+        h = 0.5;
+        if (jx < 0) {
+            h = -h;
+        }
+
+        /* |x| in [0,22], return sign(x)*0.5*(E+E/(E+1))) */
+        if (ix < 0x40360000) { /* |x|<22 */
+            if (ix < 0x3e300000) /* |x|<2**-28 */
+                if (shuge + x > 1.00000000000000000000e+00) {
+                    return x;/* ieee_sinh(tiny) = tiny with inexact */
+                }
+            t = expm1(Math.abs(x));
+            if (ix < 0x3ff00000)
+                return h * (2.0 * t - t * t / (t + 1.00000000000000000000e+00));
+            return h * (t + t / (t + 1.00000000000000000000e+00));
+        }
+
+        /* |x| in [22, ieee_log(maxdouble)] return 0.5*ieee_exp(|x|) */
+        if (ix < 0x40862E42) {
+            return h * exp(Math.abs(x));
+        }
+
+        /* |x| in [log(maxdouble), overflowthresold] */
+        final long lx = ((ONEBITS >>> 29) + ((int) bits)) & 0x00000000ffffffffL;
+        // lx = *( (((*(unsigned*)&one)>>29)) + (unsigned*)&x);
+        if (ix < 0x408633CE || (ix == 0x408633ce) && (lx <= 0x8fb9f87dL)) {
+            w = exp(0.5 * Math.abs(x));
+            t = h * w;
+            return t * w;
+        }
+
+        /* |x| > overflowthresold, ieee_sinh(x) overflow */
+        return x * shuge;
+    }
 
     /**
      * Returns the closest double approximation of the sine of the argument.
@@ -816,11 +1710,47 @@
      * <li>{@code tanh(NaN) = NaN}</li>
      * </ul>
      *
-     * @param d
+     * @param x
      *            the value whose hyperbolic tangent has to be computed.
      * @return the hyperbolic tangent of the argument
      */
-    public static native double tanh(double d);
+    public static double tanh(double x) {
+        double t, z;
+        int jx, ix;
+
+        final long bits = Double.doubleToRawLongBits(x);
+        /* High word of |x|. */
+        jx = (int) (bits >>> 32);
+        ix = jx & 0x7fffffff;
+
+        /* x is INF or NaN */
+        if (ix >= 0x7ff00000) {
+            if (jx >= 0) {
+                return 1.00000000000000000000e+00 / x + 1.00000000000000000000e+00; /* ieee_tanh(+-inf)=+-1 */
+            } else {
+                return 1.00000000000000000000e+00 / x - 1.00000000000000000000e+00; /* ieee_tanh(NaN) = NaN */
+            }
+        }
+
+        /* |x| < 22 */
+        if (ix < 0x40360000) { /* |x|<22 */
+            if (ix < 0x3c800000) { /* |x|<2**-55 */
+                return x * (1.00000000000000000000e+00 + x);/* ieee_tanh(small) = small */
+            }
+
+            if (ix >= 0x3ff00000) { /* |x|>=1 */
+                t = Math.expm1(2.0 * Math.abs(x));
+                z = 1.00000000000000000000e+00 - 2.0 / (t + 2.0);
+            } else {
+                t = Math.expm1(-2.0 * Math.abs(x));
+                z = -t / (t + 2.0);
+            }
+            /* |x| > 22, return +-1 */
+        } else {
+            z = 1.00000000000000000000e+00 - TINY; /* raised inexact flag */
+        }
+        return (jx >= 0) ? z : -z;
+    }
 
     /**
      * Returns the measure in degrees of the supplied radian angle. The result
@@ -922,6 +1852,7 @@
     /**
      * Returns a double with the given magnitude and the sign of {@code sign}.
      * If {@code sign} is NaN, the sign of the result is positive.
+     *
      * @since 1.6
      */
     public static double copySign(double magnitude, double sign) {
@@ -932,13 +1863,15 @@
         // (Tested on a Nexus One.)
         long magnitudeBits = Double.doubleToRawLongBits(magnitude);
         long signBits = Double.doubleToRawLongBits((sign != sign) ? 1.0 : sign);
-        magnitudeBits = (magnitudeBits & ~Double.SIGN_MASK) | (signBits & Double.SIGN_MASK);
+        magnitudeBits = (magnitudeBits & ~Double.SIGN_MASK)
+                | (signBits & Double.SIGN_MASK);
         return Double.longBitsToDouble(magnitudeBits);
     }
 
     /**
-     * Returns a float with the given magnitude and the sign of {@code sign}.
-     * If {@code sign} is NaN, the sign of the result is positive.
+     * Returns a float with the given magnitude and the sign of {@code sign}. If
+     * {@code sign} is NaN, the sign of the result is positive.
+     *
      * @since 1.6
      */
     public static float copySign(float magnitude, float sign) {
@@ -949,12 +1882,14 @@
         // (Tested on a Nexus One.)
         int magnitudeBits = Float.floatToRawIntBits(magnitude);
         int signBits = Float.floatToRawIntBits((sign != sign) ? 1.0f : sign);
-        magnitudeBits = (magnitudeBits & ~Float.SIGN_MASK) | (signBits & Float.SIGN_MASK);
+        magnitudeBits = (magnitudeBits & ~Float.SIGN_MASK)
+                | (signBits & Float.SIGN_MASK);
         return Float.intBitsToFloat(magnitudeBits);
     }
 
     /**
      * Returns the exponent of float {@code f}.
+     *
      * @since 1.6
      */
     public static int getExponent(float f) {
@@ -963,14 +1898,17 @@
 
     /**
      * Returns the exponent of double {@code d}.
+     *
      * @since 1.6
      */
-    public static int getExponent(double d){
+    public static int getExponent(double d) {
         return Math.getExponent(d);
     }
 
     /**
-     * Returns the next double after {@code start} in the given {@code direction}.
+     * Returns the next double after {@code start} in the given
+     * {@code direction}.
+     *
      * @since 1.6
      */
     public static double nextAfter(double start, double direction) {
@@ -981,7 +1919,9 @@
     }
 
     /**
-     * Returns the next float after {@code start} in the given {@code direction}.
+     * Returns the next float after {@code start} in the given {@code direction}
+     * .
+     *
      * @since 1.6
      */
     public static float nextAfter(float start, double direction) {
@@ -990,6 +1930,7 @@
 
     /**
      * Returns the next double larger than {@code d}.
+     *
      * @since 1.6
      */
     public static double nextUp(double d) {
@@ -998,6 +1939,7 @@
 
     /**
      * Returns the next float larger than {@code f}.
+     *
      * @since 1.6
      */
     public static float nextUp(float f) {
@@ -1006,6 +1948,7 @@
 
     /**
      * Returns {@code d} * 2^{@code scaleFactor}. The result may be rounded.
+     *
      * @since 1.6
      */
     public static double scalb(double d, int scaleFactor) {
@@ -1049,12 +1992,10 @@
         } else {
             if (Math.abs(d) >= Double.MIN_NORMAL) {
                 // common situation
-                result = ((factor + Double.EXPONENT_BIAS) << Double.MANTISSA_BITS)
-                        | (bits & Double.MANTISSA_MASK);
+                result = ((factor + Double.EXPONENT_BIAS) << Double.MANTISSA_BITS) | (bits & Double.MANTISSA_MASK);
             } else {
                 // origin d is sub-normal, change mantissa to normal style
-                result = ((factor + Double.EXPONENT_BIAS) << Double.MANTISSA_BITS)
-                        | ((bits << (subNormalFactor + 1)) & Double.MANTISSA_MASK);
+                result = ((factor + Double.EXPONENT_BIAS) << Double.MANTISSA_BITS) | ((bits << (subNormalFactor + 1)) & Double.MANTISSA_MASK);
             }
         }
         return Double.longBitsToDouble(result | sign);
@@ -1062,6 +2003,7 @@
 
     /**
      * Returns {@code d} * 2^{@code scaleFactor}. The result may be rounded.
+     *
      * @since 1.6
      */
     public static float scalb(float d, int scaleFactor) {
@@ -1073,8 +2015,7 @@
         int factor = ((bits & Float.EXPONENT_MASK) >> Float.MANTISSA_BITS)
                 - Float.EXPONENT_BIAS + scaleFactor;
         // calculates the factor of sub-normal values
-        int subNormalFactor = Integer.numberOfLeadingZeros(bits & ~Float.SIGN_MASK)
-                - Float.EXPONENT_BITS;
+        int subNormalFactor = Integer.numberOfLeadingZeros(bits & ~Float.SIGN_MASK) - Float.EXPONENT_BITS;
         if (subNormalFactor < 0) {
             // not sub-normal values
             subNormalFactor = 0;
@@ -1105,8 +2046,9 @@
                         | (bits & Float.MANTISSA_MASK);
             } else {
                 // origin d is sub-normal, change mantissa to normal style
-                result = ((factor + Float.EXPONENT_BIAS) << Float.MANTISSA_BITS)
-                        | ((bits << (subNormalFactor + 1)) & Float.MANTISSA_MASK);
+                result = ((factor + Float.EXPONENT_BIAS)
+                        << Float.MANTISSA_BITS) | (
+                        (bits << (subNormalFactor + 1)) & Float.MANTISSA_MASK);
             }
         }
         return Float.intBitsToFloat(result | sign);
@@ -1120,10 +2062,10 @@
         }
         // change it to positive
         int absDigits = -digits;
-        if (Integer.numberOfLeadingZeros(bits & ~Float.SIGN_MASK) <= (32 - absDigits)) {
+        if (Integer.numberOfLeadingZeros(bits & ~Float.SIGN_MASK)
+                <= (32 - absDigits)) {
             // some bits will remain after shifting, calculates its carry
-            if ((((bits >> (absDigits - 1)) & 0x1) == 0)
-                    || Integer.numberOfTrailingZeros(bits) == (absDigits - 1)) {
+            if ((((bits >> (absDigits - 1)) & 0x1) == 0) || Integer.numberOfTrailingZeros(bits) == (absDigits - 1)) {
                 return bits >> absDigits;
             }
             return ((bits >> absDigits) + 1);
@@ -1139,10 +2081,10 @@
         }
         // change it to positive
         long absDigits = -digits;
-        if (Long.numberOfLeadingZeros(bits & ~Double.SIGN_MASK) <= (64 - absDigits)) {
+        if (Long.numberOfLeadingZeros(bits & ~Double.SIGN_MASK)
+                <= (64 - absDigits)) {
             // some bits will remain after shifting, calculates its carry
-            if ((((bits >> (absDigits - 1)) & 0x1) == 0)
-                    || Long.numberOfTrailingZeros(bits) == (absDigits - 1)) {
+            if ((((bits >> (absDigits - 1)) & 0x1) == 0) || Long.numberOfTrailingZeros(bits) == (absDigits - 1)) {
                 return bits >> absDigits;
             }
             return ((bits >> absDigits) + 1);
diff --git a/luni/src/main/java/java/util/EnumMap.java b/luni/src/main/java/java/util/EnumMap.java
index dfacb46..eee6ff4 100644
--- a/luni/src/main/java/java/util/EnumMap.java
+++ b/luni/src/main/java/java/util/EnumMap.java
@@ -36,9 +36,9 @@
 
     private Class<K> keyType;
 
-    transient Enum[] keys;
+    transient K[] keys;
 
-    transient Object[] values;
+    transient V[] values;
 
     transient boolean[] hasMapping;
 
@@ -48,8 +48,7 @@
 
     private transient EnumMapEntrySet<K, V> entrySet = null;
 
-    private static class Entry<KT extends Enum<KT>, VT> extends
-            MapEntry<KT, VT> {
+    private static class Entry<KT extends Enum<KT>, VT> extends MapEntry<KT, VT> {
         private final EnumMap<KT, VT> enumMap;
 
         private final int ordinal;
@@ -57,10 +56,9 @@
         Entry(KT theKey, VT theValue, EnumMap<KT, VT> em) {
             super(theKey, theValue);
             enumMap = em;
-            ordinal = ((Enum) theKey).ordinal();
+            ordinal = theKey.ordinal();
         }
 
-        @SuppressWarnings("unchecked")
         @Override
         public boolean equals(Object object) {
             if (!enumMap.hasMapping[ordinal]) {
@@ -68,7 +66,7 @@
             }
             boolean isEqual = false;
             if (object instanceof Map.Entry) {
-                Map.Entry<KT, VT> entry = (Map.Entry<KT, VT>) object;
+                Map.Entry<?, ?> entry = (Map.Entry<?, ?>) object;
                 Object enumKey = entry.getKey();
                 if (key.equals(enumKey)) {
                     Object theValue = entry.getValue();
@@ -84,37 +82,32 @@
 
         @Override
         public int hashCode() {
-            return (enumMap.keys[ordinal] == null ? 0 : enumMap.keys[ordinal]
-                    .hashCode())
+            return (enumMap.keys[ordinal] == null ? 0 : enumMap.keys[ordinal].hashCode())
                     ^ (enumMap.values[ordinal] == null ? 0
                             : enumMap.values[ordinal].hashCode());
         }
 
-        @SuppressWarnings("unchecked")
         @Override
         public KT getKey() {
             checkEntryStatus();
-            return (KT) enumMap.keys[ordinal];
+            return enumMap.keys[ordinal];
         }
 
-        @SuppressWarnings("unchecked")
         @Override
         public VT getValue() {
             checkEntryStatus();
-            return (VT) enumMap.values[ordinal];
+            return enumMap.values[ordinal];
         }
 
-        @SuppressWarnings("unchecked")
         @Override
         public VT setValue(VT value) {
             checkEntryStatus();
-            return enumMap.put((KT) enumMap.keys[ordinal], value);
+            return enumMap.put(enumMap.keys[ordinal], value);
         }
 
         @Override
         public String toString() {
-            StringBuilder result = new StringBuilder(enumMap.keys[ordinal]
-                    .toString());
+            StringBuilder result = new StringBuilder(enumMap.keys[ordinal].toString());
             result.append("=");
             result.append(enumMap.values[ordinal] == null
                     ? "null" : enumMap.values[ordinal].toString());
@@ -128,8 +121,7 @@
         }
     }
 
-    private static class EnumMapIterator<E, KT extends Enum<KT>, VT> implements
-            Iterator<E> {
+    private static class EnumMapIterator<E, KT extends Enum<KT>, VT> implements Iterator<E> {
         int position = 0;
 
         int prePosition = -1;
@@ -153,13 +145,12 @@
             return position != length;
         }
 
-        @SuppressWarnings("unchecked")
         public E next() {
             if (!hasNext()) {
                 throw new NoSuchElementException();
             }
             prePosition = position++;
-            return type.get(new MapEntry(enumMap.keys[prePosition],
+            return type.get(new MapEntry<KT, VT>(enumMap.keys[prePosition],
                     enumMap.values[prePosition]));
         }
 
@@ -172,13 +163,12 @@
         }
 
         @Override
-        @SuppressWarnings("unchecked")
         public String toString() {
             if (prePosition == -1) {
                 return super.toString();
             }
             return type.get(
-                    new MapEntry(enumMap.keys[prePosition],
+                    new MapEntry<KT, VT>(enumMap.keys[prePosition],
                             enumMap.values[prePosition])).toString();
         }
 
@@ -208,8 +198,7 @@
         }
 
         @Override
-        @SuppressWarnings("unchecked")
-        public Iterator iterator() {
+        public Iterator<KT> iterator() {
             return new EnumMapIterator<KT, KT, VT>(
                     new MapEntry.Type<KT, KT, VT>() {
                         public KT get(MapEntry<KT, VT> entry) {
@@ -219,7 +208,6 @@
         }
 
         @Override
-        @SuppressWarnings("unchecked")
         public boolean remove(Object object) {
             if (contains(object)) {
                 enumMap.remove(object);
@@ -252,9 +240,8 @@
             return enumMap.containsValue(object);
         }
 
-        @SuppressWarnings("unchecked")
         @Override
-        public Iterator iterator() {
+        public Iterator<VT> iterator() {
             return new EnumMapIterator<VT, KT, VT>(
                     new MapEntry.Type<VT, KT, VT>() {
                         public VT get(MapEntry<KT, VT> entry) {
@@ -296,15 +283,14 @@
             super(value, em);
         }
 
-        @SuppressWarnings("unchecked")
         @Override
         public E next() {
             if (!hasNext()) {
                 throw new NoSuchElementException();
             }
             prePosition = position++;
-            return type.get(new Entry<KT, VT>((KT) enumMap.keys[prePosition],
-                    (VT) enumMap.values[prePosition], enumMap));
+            return type.get(new EnumMap.Entry<KT, VT>(enumMap.keys[prePosition],
+                    enumMap.values[prePosition], enumMap));
         }
     }
 
@@ -325,8 +311,8 @@
         public boolean contains(Object object) {
             boolean isEqual = false;
             if (object instanceof Map.Entry) {
-                Object enumKey = ((Map.Entry) object).getKey();
-                Object enumValue = ((Map.Entry) object).getValue();
+                Object enumKey = ((Map.Entry<?, ?>) object).getKey();
+                Object enumValue = ((Map.Entry<?, ?>) object).getValue();
                 if (enumMap.containsKey(enumKey)) {
                     VT value = enumMap.get(enumKey);
                     if (value == null) {
@@ -352,7 +338,7 @@
         @Override
         public boolean remove(Object object) {
             if (contains(object)) {
-                enumMap.remove(((Map.Entry) object).getKey());
+                enumMap.remove(((Map.Entry<?, ?>) object).getKey());
                 return true;
             }
             return false;
@@ -369,21 +355,22 @@
             return toArray(entryArray);
         }
 
-        @SuppressWarnings("unchecked")
         @Override
-        public Object[] toArray(Object[] array) {
+        public <T> T[] toArray(T[] array) {
             int size = enumMap.size();
             int index = 0;
-            Object[] entryArray = array;
+            T[] entryArray = array;
             if (size > array.length) {
                 Class<?> clazz = array.getClass().getComponentType();
-                entryArray = (Object[]) Array.newInstance(clazz, size);
+                @SuppressWarnings("unchecked") T[] newArray = (T[]) Array.newInstance(clazz, size);
+                entryArray = newArray;
             }
             Iterator<Map.Entry<KT, VT>> iter = iterator();
             for (; index < size; index++) {
                 Map.Entry<KT, VT> entry = iter.next();
-                entryArray[index] = new MapEntry<KT, VT>(entry.getKey(), entry
-                        .getValue());
+                @SuppressWarnings("unchecked") T newEntry =
+                        (T) new MapEntry<KT, VT>(entry.getKey(), entry.getValue());
+                entryArray[index] = newEntry;
             }
             if (index < array.length) {
                 entryArray[index] = null;
@@ -431,22 +418,27 @@
      * @throws NullPointerException
      *             if {@code map} is {@code null}.
      */
-    @SuppressWarnings("unchecked")
     public EnumMap(Map<K, ? extends V> map) {
         if (map instanceof EnumMap) {
-            initialization((EnumMap<K, V>) map);
+            @SuppressWarnings("unchecked") EnumMap<K, ? extends V> enumMap =
+                    (EnumMap<K, ? extends V>) map;
+            initialization(enumMap);
         } else {
             if (map.isEmpty()) {
                 throw new IllegalArgumentException("map is empty");
             }
             Iterator<K> iter = map.keySet().iterator();
             K enumKey = iter.next();
-            Class clazz = enumKey.getClass();
-            if (clazz.isEnum()) {
-                initialization(clazz);
-            } else {
-                initialization(clazz.getSuperclass());
+            // Confirm the key is actually an enum: Throw ClassCastException if not.
+            Enum.class.cast(enumKey);
+            Class<?> clazz = enumKey.getClass();
+            if (!clazz.isEnum()) {
+                // Each enum value can have its own subclass. In this case we want the abstract
+                // super-class which has the values() method.
+                clazz = clazz.getSuperclass();
             }
+            @SuppressWarnings("unchecked") Class<K> enumClass = (Class<K>) clazz;
+            initialization(enumClass);
             putAllImpl(map);
         }
     }
@@ -469,11 +461,10 @@
      *
      * @return a shallow copy of this {@code EnumMap}.
      */
-    @SuppressWarnings("unchecked")
     @Override
     public EnumMap<K, V> clone() {
         try {
-            EnumMap<K, V> enumMap = (EnumMap<K, V>) super.clone();
+            @SuppressWarnings("unchecked") EnumMap<K, V> enumMap = (EnumMap<K, V>) super.clone();
             enumMap.initialization(this);
             return enumMap;
         } catch (CloneNotSupportedException e) {
@@ -553,7 +544,6 @@
      * @see #hashCode()
      * @see #entrySet()
      */
-    @SuppressWarnings("unchecked")
     @Override
     public boolean equals(Object object) {
         if (this == object) {
@@ -562,7 +552,7 @@
         if (!(object instanceof EnumMap)) {
             return super.equals(object);
         }
-        EnumMap<K, V> enumMap = (EnumMap<K, V>) object;
+        @SuppressWarnings("unchecked") EnumMap<K, V> enumMap = (EnumMap<K, V>) object;
         if (keyType != enumMap.keyType || size() != enumMap.size()) {
             return false;
         }
@@ -579,13 +569,12 @@
      *         if no mapping for the specified key is found.
      */
     @Override
-    @SuppressWarnings("unchecked")
     public V get(Object key) {
         if (!isValidKeyType(key)) {
             return null;
         }
         int keyOrdinal = ((Enum) key).ordinal();
-        return (V) values[keyOrdinal];
+        return values[keyOrdinal];
     }
 
     /**
@@ -627,7 +616,6 @@
      *                support {@code null} keys or values.
      */
     @Override
-    @SuppressWarnings("unchecked")
     public V put(K key, V value) {
         return putImpl(key, value);
     }
@@ -649,7 +637,6 @@
      *                support {@code null} keys or values.
      */
     @Override
-    @SuppressWarnings("unchecked")
     public void putAll(Map<? extends K, ? extends V> map) {
         putAllImpl(map);
     }
@@ -665,7 +652,6 @@
      *                if removing from this {@code EnumMap} is not supported.
      */
     @Override
-    @SuppressWarnings("unchecked")
     public V remove(Object key) {
         if (!isValidKeyType(key)) {
             return null;
@@ -675,7 +661,7 @@
             hasMapping[keyOrdinal] = false;
             mappingsCount--;
         }
-        V oldValue = (V) values[keyOrdinal];
+        V oldValue = values[keyOrdinal];
         values[keyOrdinal] = null;
         return oldValue;
     }
@@ -716,35 +702,29 @@
         stream.defaultReadObject();
         initialization(keyType);
         int elementCount = stream.readInt();
-        Enum<K> enumKey;
-        Object value;
+        K enumKey;
+        V value;
         for (int i = elementCount; i > 0; i--) {
-            enumKey = (Enum<K>) stream.readObject();
-            value = stream.readObject();
-            putImpl((K) enumKey, (V) value);
+            enumKey = (K) stream.readObject();
+            value = (V) stream.readObject();
+            putImpl(enumKey, value);
         }
     }
 
     private void writeObject(ObjectOutputStream stream) throws IOException {
         stream.defaultWriteObject();
         stream.writeInt(mappingsCount);
-        Iterator<Map.Entry<K, V>> iterator = entrySet().iterator();
-        while (iterator.hasNext()) {
-            Map.Entry<K, V> entry = iterator.next();
+        for (Map.Entry<K, V> entry : entrySet()) {
             stream.writeObject(entry.getKey());
             stream.writeObject(entry.getValue());
         }
     }
 
     private boolean isValidKeyType(Object key) {
-        if (key != null && keyType.isInstance(key)) {
-            return true;
-        }
-        return false;
+        return key != null && keyType.isInstance(key);
     }
 
-    @SuppressWarnings("unchecked")
-    private void initialization(EnumMap enumMap) {
+    private void initialization(EnumMap<K, ? extends V> enumMap) {
         keyType = enumMap.keyType;
         keys = enumMap.keys;
         enumSize = enumMap.enumSize;
@@ -757,20 +737,19 @@
         keyType = type;
         keys = Enum.getSharedConstants(keyType);
         enumSize = keys.length;
-        values = new Object[enumSize];
+        // The value array is actually Object[] for speed of creation. It is treated as a V[]
+        // because it is safe to do so and eliminates unchecked warning suppression throughout.
+        @SuppressWarnings("unchecked") V[] valueArray = (V[]) new Object[enumSize];
+        values = valueArray;
         hasMapping = new boolean[enumSize];
     }
 
-    @SuppressWarnings("unchecked")
-    private void putAllImpl(Map map) {
-        Iterator iter = map.entrySet().iterator();
-        while (iter.hasNext()) {
-            Map.Entry entry = (Map.Entry) iter.next();
-            putImpl((K) entry.getKey(), (V) entry.getValue());
+    private void putAllImpl(Map<? extends K, ? extends V> map) {
+        for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {
+            putImpl(entry.getKey(), entry.getValue());
         }
     }
 
-    @SuppressWarnings("unchecked")
     private V putImpl(K key, V value) {
         if (key == null) {
             throw new NullPointerException("key == null");
@@ -781,7 +760,7 @@
             hasMapping[keyOrdinal] = true;
             mappingsCount++;
         }
-        V oldValue = (V) values[keyOrdinal];
+        V oldValue = values[keyOrdinal];
         values[keyOrdinal] = value;
         return oldValue;
     }
diff --git a/luni/src/main/java/java/util/logging/FileHandler.java b/luni/src/main/java/java/util/logging/FileHandler.java
index 6ffef87..1fd1dbf 100644
--- a/luni/src/main/java/java/util/logging/FileHandler.java
+++ b/luni/src/main/java/java/util/logging/FileHandler.java
@@ -261,15 +261,15 @@
         boolean hasUniqueID = false;
         boolean hasGeneration = false;
 
-        // TODO privilege code?
+        String homePath = System.getProperty("user.home");
+        if (homePath == null) {
+            throw new NullPointerException("System property \"user.home\" is null");
+        }
+        boolean homePathHasSepEnd = homePath.endsWith(File.separator);
 
         String tempPath = System.getProperty("java.io.tmpdir");
-        boolean tempPathHasSepEnd = (tempPath == null ? false : tempPath
-                .endsWith(File.separator));
-
-        String homePath = System.getProperty("user.home");
-        boolean homePathHasSepEnd = (homePath == null ? false : homePath
-                .endsWith(File.separator));
+        tempPath = tempPath == null ? homePath : tempPath;
+        boolean tempPathHasSepEnd = tempPath.endsWith(File.separator);
 
         StringBuilder sb = new StringBuilder();
         pattern = pattern.replace('/', File.separatorChar);
diff --git a/luni/src/main/java/java/util/logging/SocketHandler.java b/luni/src/main/java/java/util/logging/SocketHandler.java
index 48bfc0e..c6d4be0 100644
--- a/luni/src/main/java/java/util/logging/SocketHandler.java
+++ b/luni/src/main/java/java/util/logging/SocketHandler.java
@@ -106,9 +106,13 @@
             throw new IllegalArgumentException("host == null || host.isEmpty()");
         }
         // check the validity of the port number
-        int p = 0;
+        int p;
         try {
             p = Integer.parsePositiveInt(port);
+            // Must be >= 0 to get this far. 0 is invalid too.
+            if (p == 0) {
+                throw new IllegalArgumentException("Illegal port argument " + port);
+            }
         } catch (NumberFormatException e) {
             throw new IllegalArgumentException("Illegal port argument " + port);
         }
diff --git a/luni/src/main/java/java/util/logging/XMLFormatter.java b/luni/src/main/java/java/util/logging/XMLFormatter.java
index 0d80b3e..3952596 100644
--- a/luni/src/main/java/java/util/logging/XMLFormatter.java
+++ b/luni/src/main/java/java/util/logging/XMLFormatter.java
@@ -17,6 +17,7 @@
 
 package java.util.logging;
 
+import java.io.IOException;
 import java.text.MessageFormat;
 import java.util.Date;
 import java.util.ResourceBundle;
@@ -50,7 +51,7 @@
         // call a method of LogRecord to ensure not null
         long time = r.getMillis();
         // format to date
-        String date = MessageFormat.format("{0, date} {0, time}", new Object[] { new Date(time) });
+        String date = MessageFormat.format("{0, date} {0, time}", new Date(time));
         String nl = System.lineSeparator();
 
         StringBuilder sb = new StringBuilder();
@@ -59,21 +60,21 @@
         append(sb, 1, "millis", time);
         append(sb, 1, "sequence", r.getSequenceNumber());
         if (r.getLoggerName() != null) {
-            append(sb, 1, "logger", r.getLoggerName());
+            escapeAndAppend(sb, 1, "logger", r.getLoggerName());
         }
         append(sb, 1, "level", r.getLevel().getName());
         if (r.getSourceClassName() != null) {
             append(sb, 1, "class", r.getSourceClassName());
         }
         if (r.getSourceMethodName() != null) {
-            append(sb, 1, "method", r.getSourceMethodName());
+            escapeAndAppend(sb, 1, "method", r.getSourceMethodName());
         }
         append(sb, 1, "thread", r.getThreadID());
         formatMessages(r, sb);
         Object[] params = r.getParameters();
         if (params != null) {
             for (Object element : params) {
-                append(sb, 1, "param", element);
+                escapeAndAppend(sb, 1, "param", element);
             }
         }
         formatThrowable(r, sb);
@@ -96,14 +97,14 @@
 
             if (message == null) {
                 message = pattern;
-                append(sb, 1, "message", message);
+                escapeAndAppend(sb, 1, "message", message);
             } else {
-                append(sb, 1, "message", message);
-                append(sb, 1, "key", pattern);
-                append(sb, 1, "catalog", r.getResourceBundleName());
+                escapeAndAppend(sb, 1, "message", message);
+                escapeAndAppend(sb, 1, "key", pattern);
+                escapeAndAppend(sb, 1, "catalog", r.getResourceBundleName());
             }
         } else if (pattern != null) {
-            append(sb, 1, "message", pattern);
+            escapeAndAppend(sb, 1, "message", pattern);
         } else {
             sb.append(indent).append("<message/>");
         }
@@ -114,13 +115,13 @@
         if ((t = r.getThrown()) != null) {
             String nl = System.lineSeparator();
             sb.append(indent).append("<exception>").append(nl);
-            append(sb, 2, "message", t.toString());
+            escapeAndAppend(sb, 2, "message", t.toString());
             // format throwable's stack trace
             StackTraceElement[] elements = t.getStackTrace();
             for (StackTraceElement e : elements) {
                 sb.append(indent).append(indent).append("<frame>").append(nl);
                 append(sb, 3, "class", e.getClassName());
-                append(sb, 3, "method", e.getMethodName());
+                escapeAndAppend(sb, 3, "method", e.getMethodName());
                 append(sb, 3, "line", e.getLineNumber());
                 sb.append(indent).append(indent).append("</frame>").append(nl);
             }
@@ -138,6 +139,49 @@
         sb.append(System.lineSeparator());
     }
 
+    private static void escapeAndAppend(StringBuilder sb, int indentCount, String tag, Object value) {
+        if (value == null) {
+            append(sb, indentCount, tag, value);
+        } else {
+            for (int i = 0; i < indentCount; ++i) {
+                sb.append(indent);
+            }
+            sb.append("<").append(tag).append(">");
+            try {
+                escapeXml(sb, value.toString());
+            } catch (IOException e) {
+                throw new AssertionError();
+            }
+            sb.append("</").append(tag).append(">");
+            sb.append(System.lineSeparator());
+        }
+    }
+
+    private static void escapeXml(Appendable valueBuilder, String value) throws IOException {
+        for (int i = 0; i < value.length(); i++) {
+            char c = value.charAt(i);
+            switch (c) {
+                case '\"':
+                    valueBuilder.append("&quot;");
+                    break;
+                case '>':
+                    valueBuilder.append("&gt;");
+                    break;
+                case '<':
+                    valueBuilder.append("&lt;");
+                    break;
+                case '&':
+                    valueBuilder.append("&amp;");
+                    break;
+                case '\'':
+                    valueBuilder.append("&apos;");
+                    break;
+                default:
+                    valueBuilder.append(c);
+            }
+        }
+    }
+
     /**
      * Returns the header string for a set of log records formatted as XML
      * strings, using the output handler's encoding if it is defined, otherwise
diff --git a/luni/src/main/java/java/util/zip/ZipEntry.java b/luni/src/main/java/java/util/zip/ZipEntry.java
index 217cc3c..d007b0f 100644
--- a/luni/src/main/java/java/util/zip/ZipEntry.java
+++ b/luni/src/main/java/java/util/zip/ZipEntry.java
@@ -52,7 +52,6 @@
 
     byte[] extra;
 
-    int nameLength = -1;
     long localHeaderRelOffset = -1;
 
     long dataOffset = -1;
@@ -69,7 +68,7 @@
 
     ZipEntry(String name, String comment, long crc, long compressedSize,
             long size, int compressionMethod, int time, int modDate, byte[] extra,
-            int nameLength, long localHeaderRelOffset, long dataOffset) {
+            long localHeaderRelOffset, long dataOffset) {
         this.name = name;
         this.comment = comment;
         this.crc = crc;
@@ -79,7 +78,6 @@
         this.time = time;
         this.modDate = modDate;
         this.extra = extra;
-        this.nameLength = nameLength;
         this.localHeaderRelOffset = localHeaderRelOffset;
         this.dataOffset = dataOffset;
     }
@@ -340,7 +338,6 @@
         compressionMethod = ze.compressionMethod;
         modDate = ze.modDate;
         extra = ze.extra;
-        nameLength = ze.nameLength;
         localHeaderRelOffset = ze.localHeaderRelOffset;
         dataOffset = ze.dataOffset;
     }
@@ -412,7 +409,7 @@
         compressedSize = ((long) it.readInt()) & 0xffffffffL;
         size = ((long) it.readInt()) & 0xffffffffL;
 
-        nameLength = it.readShort() & 0xffff;
+        int nameLength = it.readShort() & 0xffff;
         int extraLength = it.readShort() & 0xffff;
         int commentByteCount = it.readShort() & 0xffff;
 
diff --git a/luni/src/main/java/javax/net/ssl/DefaultHostnameVerifier.java b/luni/src/main/java/javax/net/ssl/DefaultHostnameVerifier.java
index fa11371..bff63b5 100644
--- a/luni/src/main/java/javax/net/ssl/DefaultHostnameVerifier.java
+++ b/luni/src/main/java/javax/net/ssl/DefaultHostnameVerifier.java
@@ -131,12 +131,24 @@
             return false;
         }
 
+        if (hostName.endsWith(".") && !cn.endsWith(".")) {
+            // "www.android.com." matches "www.android.com"
+            // This is needed because server certificates do not normally contain absolute names
+            // or patterns. Connections via absolute hostnames should be supported and even
+            // preferred over those via relative hostnames, to avoid DNS suffixes being appended.
+            cn += '.';
+        }
+
         cn = cn.toLowerCase(Locale.US);
 
         if (!cn.contains("*")) {
             return hostName.equals(cn);
         }
 
+        if (!containsAtLeastTwoDomainNameLabelsExcludingRoot(cn)) {
+            return false; // reject matches where the wildcard pattern consists of only one label.
+        }
+
         if (cn.startsWith("*.") && hostName.regionMatches(0, cn, 2, cn.length() - 2)) {
             return true; // "*.foo.com" matches "foo.com"
         }
@@ -166,4 +178,27 @@
 
         return true;
     }
+
+    /**
+     * Checks whether the provided hostname consists of at least two domain name labels, excluding
+     * the root label.
+     *
+     * <p>For example, this method returns {@code true} for {@code www.android.com} and
+     * {@code foo.com} and {@code foo.com.}, and returns {@code false} for {@code foo} and
+     * {@code foo.}.
+     */
+    private static boolean containsAtLeastTwoDomainNameLabelsExcludingRoot(String hostname) {
+        int delimiterIndex = hostname.indexOf('.');
+        if (delimiterIndex == -1) {
+            // No delimiters -- only one label
+            return false;
+        }
+        if (delimiterIndex == hostname.length() - 1) {
+            // Only one delimiter at the every end of the hostname -- this is an absolute hostname
+            // consisting of one label
+            return false;
+        }
+        // At least two labels
+        return true;
+    }
 }
diff --git a/luni/src/main/native/java_lang_StrictMath.cpp b/luni/src/main/native/java_lang_StrictMath.cpp
index cfe375e..e8c6dfb 100644
--- a/luni/src/main/native/java_lang_StrictMath.cpp
+++ b/luni/src/main/native/java_lang_StrictMath.cpp
@@ -34,26 +34,6 @@
     return ieee_tan(a);
 }
 
-static jdouble StrictMath_asin(JNIEnv*, jclass, jdouble a) {
-    return ieee_asin(a);
-}
-
-static jdouble StrictMath_acos(JNIEnv*, jclass, jdouble a) {
-    return ieee_acos(a);
-}
-
-static jdouble StrictMath_atan(JNIEnv*, jclass, jdouble a) {
-    return ieee_atan(a);
-}
-
-static jdouble StrictMath_exp(JNIEnv*, jclass, jdouble a) {
-    return ieee_exp(a);
-}
-
-static jdouble StrictMath_log(JNIEnv*, jclass, jdouble a) {
-    return ieee_log(a);
-}
-
 static jdouble StrictMath_sqrt(JNIEnv*, jclass, jdouble a) {
     return ieee_sqrt(a);
 }
@@ -74,75 +54,30 @@
     return ieee_rint(a);
 }
 
-static jdouble StrictMath_atan2(JNIEnv*, jclass, jdouble a, jdouble b) {
-    return ieee_atan2(a, b);
-}
-
 static jdouble StrictMath_pow(JNIEnv*, jclass, jdouble a, jdouble b) {
     return ieee_pow(a,b);
 }
 
-static jdouble StrictMath_sinh(JNIEnv*, jclass, jdouble a) {
-    return ieee_sinh(a);
-}
-
-static jdouble StrictMath_tanh(JNIEnv*, jclass, jdouble a) {
-    return ieee_tanh(a);
-}
-
-static jdouble StrictMath_cosh(JNIEnv*, jclass, jdouble a) {
-    return ieee_cosh(a);
-}
-
-static jdouble StrictMath_log10(JNIEnv*, jclass, jdouble a) {
-    return ieee_log10(a);
-}
-
-static jdouble StrictMath_cbrt(JNIEnv*, jclass, jdouble a) {
-    return ieee_cbrt(a);
-}
-
-static jdouble StrictMath_expm1(JNIEnv*, jclass, jdouble a) {
-    return ieee_expm1(a);
-}
-
 static jdouble StrictMath_hypot(JNIEnv*, jclass, jdouble a, jdouble b) {
     return ieee_hypot(a, b);
 }
 
-static jdouble StrictMath_log1p(JNIEnv*, jclass, jdouble a) {
-    return ieee_log1p(a);
-}
-
 static jdouble StrictMath_nextafter(JNIEnv*, jclass, jdouble a, jdouble b) {
     return ieee_nextafter(a, b);
 }
 
 static JNINativeMethod gMethods[] = {
     NATIVE_METHOD(StrictMath, IEEEremainder, "!(DD)D"),
-    NATIVE_METHOD(StrictMath, acos, "!(D)D"),
-    NATIVE_METHOD(StrictMath, asin, "!(D)D"),
-    NATIVE_METHOD(StrictMath, atan, "!(D)D"),
-    NATIVE_METHOD(StrictMath, atan2, "!(DD)D"),
-    NATIVE_METHOD(StrictMath, cbrt, "!(D)D"),
     NATIVE_METHOD(StrictMath, ceil, "!(D)D"),
     NATIVE_METHOD(StrictMath, cos, "!(D)D"),
-    NATIVE_METHOD(StrictMath, cosh, "!(D)D"),
-    NATIVE_METHOD(StrictMath, exp, "!(D)D"),
-    NATIVE_METHOD(StrictMath, expm1, "!(D)D"),
     NATIVE_METHOD(StrictMath, floor, "!(D)D"),
     NATIVE_METHOD(StrictMath, hypot, "!(DD)D"),
-    NATIVE_METHOD(StrictMath, log, "!(D)D"),
-    NATIVE_METHOD(StrictMath, log10, "!(D)D"),
-    NATIVE_METHOD(StrictMath, log1p, "!(D)D"),
     NATIVE_METHOD(StrictMath, nextafter, "!(DD)D"),
     NATIVE_METHOD(StrictMath, pow, "!(DD)D"),
     NATIVE_METHOD(StrictMath, rint, "!(D)D"),
     NATIVE_METHOD(StrictMath, sin, "!(D)D"),
-    NATIVE_METHOD(StrictMath, sinh, "!(D)D"),
     NATIVE_METHOD(StrictMath, sqrt, "!(D)D"),
     NATIVE_METHOD(StrictMath, tan, "!(D)D"),
-    NATIVE_METHOD(StrictMath, tanh, "!(D)D"),
 };
 void register_java_lang_StrictMath(JNIEnv* env) {
     jniRegisterNativeMethods(env, "java/lang/StrictMath", gMethods, NELEM(gMethods));
diff --git a/luni/src/main/native/java_lang_System.cpp b/luni/src/main/native/java_lang_System.cpp
index 944c0c3..c237ce4 100644
--- a/luni/src/main/native/java_lang_System.cpp
+++ b/luni/src/main/native/java_lang_System.cpp
@@ -84,7 +84,11 @@
     properties.push_back(std::string("user.dir=") + getcwd(path, sizeof(path)));
 
     properties.push_back("android.zlib.version=" ZLIB_VERSION);
+#if defined(OPENSSL_IS_BORINGSSL)
+    properties.push_back("android.openssl.version=BoringSSL");
+#else
     properties.push_back("android.openssl.version=" OPENSSL_VERSION_TEXT);
+#endif
 
     const char* library_path = getenv("LD_LIBRARY_PATH");
 #if defined(HAVE_ANDROID_OS)
diff --git a/luni/src/main/native/java_math_NativeBN.cpp b/luni/src/main/native/java_math_NativeBN.cpp
index be87ea6..e27ef03 100644
--- a/luni/src/main/native/java_math_NativeBN.cpp
+++ b/luni/src/main/native/java_math_NativeBN.cpp
@@ -28,6 +28,18 @@
 #include <openssl/err.h>
 #include <stdio.h>
 
+#if defined(OPENSSL_IS_BORINGSSL)
+/* BoringSSL no longer exports |bn_check_top|. */
+static void bn_check_top(const BIGNUM* bn) {
+  /* This asserts that |bn->top| (which contains the number of elements of
+   * |bn->d| that are valid) is minimal. In other words, that there aren't
+   * superfluous zeros. */
+  if (bn != NULL && bn->top != 0 && bn->d[bn->top-1] == 0) {
+    abort();
+  }
+}
+#endif
+
 struct BN_CTX_Deleter {
   void operator()(BN_CTX* p) const {
     BN_CTX_free(p);
@@ -109,28 +121,32 @@
 }
 
 static void NativeBN_putULongInt(JNIEnv* env, jclass, jlong a0, jlong java_dw, jboolean neg) {
-    if (!oneValidHandle(env, a0)) return;
+  if (!oneValidHandle(env, a0)) return;
 
-    uint64_t dw = java_dw;
+  uint64_t dw = java_dw;
+  BIGNUM* a = toBigNum(a0);
+  int ok;
 
-    // cf. litEndInts2bn:
-    BIGNUM* a = toBigNum(a0);
-    bn_check_top(a);
-    if (bn_wexpand(a, 8/BN_BYTES) != NULL) {
-#ifdef __LP64__
+  static_assert(sizeof(dw) == sizeof(BN_ULONG) ||
+                sizeof(dw) == 2*sizeof(BN_ULONG), "Unknown BN configuration");
+
+  if (sizeof(dw) == sizeof(BN_ULONG)) {
+    ok = BN_set_word(a, dw);
+  } else if (sizeof(dw) == 2 * sizeof(BN_ULONG)) {
+    ok = (bn_wexpand(a, 2) != NULL);
+    if (ok) {
       a->d[0] = dw;
-#else
-      unsigned int hi = dw >> 32; // This shifts without sign extension.
-      int lo = (int)dw; // This truncates implicitly.
-      a->d[0] = lo;
-      a->d[1] = hi;
-#endif
-      a->top = 8 / BN_BYTES;
-      a->neg = neg;
+      a->d[1] = dw >> 32;
+      a->top = 2;
       bn_correct_top(a);
-    } else {
-      throwExceptionIfNecessary(env);
     }
+  }
+
+  BN_set_negative(a, neg);
+
+  if (!ok) {
+    throwExceptionIfNecessary(env);
+  }
 }
 
 static void NativeBN_putLongInt(JNIEnv* env, jclass cls, jlong a, jlong dw) {
@@ -240,25 +256,25 @@
 
   bn_check_top(ret);
   // FIXME: assert bytesLen > 0
-  int wLen = (bytesLen + BN_BYTES - 1) / BN_BYTES;
+  int wLen = (bytesLen + sizeof(BN_ULONG) - 1) / sizeof(BN_ULONG);
   int firstNonzeroDigit = -2;
   if (bn_wexpand(ret, wLen) != NULL) {
     BN_ULONG* d = ret->d;
     BN_ULONG di;
     ret->top = wLen;
-    int highBytes = bytesLen % BN_BYTES;
+    int highBytes = bytesLen % sizeof(BN_ULONG);
     int k = bytesLen;
     // Put bytes to the int array starting from the end of the byte array
     int i = 0;
     while (k > highBytes) {
-      k -= BN_BYTES;
+      k -= sizeof(BN_ULONG);
       di = BYTES2ULONG(bytes, k);
       if (di != 0) {
         d[i] = -di;
         firstNonzeroDigit = i;
         i++;
         while (k > highBytes) {
-          k -= BN_BYTES;
+          k -= sizeof(BN_ULONG);
           d[i] = ~BYTES2ULONG(bytes, k);
           i++;
         }
@@ -394,7 +410,7 @@
   if (wLen == 0) {
     return NULL;
   }
-  jintArray result = env->NewIntArray(wLen * BN_BYTES/sizeof(unsigned int));
+  jintArray result = env->NewIntArray(wLen * sizeof(BN_ULONG)/sizeof(unsigned int));
   if (result == NULL) {
     return NULL;
   }
@@ -445,7 +461,7 @@
     do { i--; } while (!((i < 0) || (d[i] != 0)));
     if (i < 0) msd--; // Only if all lower significant digits are 0 we decrement the most significant one.
   }
-  return (wLen - 1) * BN_BYTES * 8 + BN_num_bits_word(msd);
+  return (wLen - 1) * sizeof(BN_ULONG) * 8 + BN_num_bits_word(msd);
 }
 
 static jboolean NativeBN_BN_is_bit_set(JNIEnv* env, jclass, jlong a, int n) {
diff --git a/luni/src/main/native/java_util_jar_StrictJarFile.cpp b/luni/src/main/native/java_util_jar_StrictJarFile.cpp
index 7611749..b10ec43 100644
--- a/luni/src/main/native/java_util_jar_StrictJarFile.cpp
+++ b/luni/src/main/native/java_util_jar_StrictJarFile.cpp
@@ -32,11 +32,10 @@
   jniThrowException(env, "java/io/IOException", ErrorCodeString(errorCode));
 }
 
-static jobject newZipEntry(JNIEnv* env, const ZipEntry& entry, jstring entryName,
-                           const uint16_t nameLength) {
+static jobject newZipEntry(JNIEnv* env, const ZipEntry& entry, jstring entryName) {
   ScopedLocalRef<jclass> zipEntryClass(env, env->FindClass("java/util/zip/ZipEntry"));
   const jmethodID zipEntryCtor = env->GetMethodID(zipEntryClass.get(), "<init>",
-                                   "(Ljava/lang/String;Ljava/lang/String;JJJIII[BIJJ)V");
+                                   "(Ljava/lang/String;Ljava/lang/String;JJJIII[BJJ)V");
 
   return env->NewObject(zipEntryClass.get(),
                         zipEntryCtor,
@@ -49,7 +48,6 @@
                         static_cast<jint>(0),  // time
                         static_cast<jint>(0),  // modData
                         NULL,  // byte[] extra
-                        static_cast<jint>(nameLength),
                         static_cast<jlong>(-1),  // local header offset
                         static_cast<jlong>(entry.offset));
 }
@@ -72,25 +70,20 @@
 
 class IterationHandle {
  public:
-  IterationHandle(const char* prefix) :
-    cookie_(NULL), prefix_(strdup(prefix)) {
+  IterationHandle() :
+    cookie_(NULL) {
   }
 
   void** CookieAddress() {
     return &cookie_;
   }
 
-  const char* Prefix() const {
-    return prefix_;
-  }
-
   ~IterationHandle() {
-    free(prefix_);
+    EndIteration(cookie_);
   }
 
  private:
   void* cookie_;
-  char* prefix_;
 };
 
 
@@ -101,14 +94,15 @@
     return static_cast<jlong>(-1);
   }
 
-  IterationHandle* handle = new IterationHandle(prefixChars.c_str());
+  IterationHandle* handle = new IterationHandle();
   int32_t error = 0;
   if (prefixChars.size() == 0) {
     error = StartIteration(reinterpret_cast<ZipArchiveHandle>(nativeHandle),
                            handle->CookieAddress(), NULL);
   } else {
+    ZipEntryName entry_name(prefixChars.c_str());
     error = StartIteration(reinterpret_cast<ZipArchiveHandle>(nativeHandle),
-                           handle->CookieAddress(), handle->Prefix());
+                           handle->CookieAddress(), &entry_name);
   }
 
   if (error) {
@@ -135,7 +129,7 @@
   entryNameCString[entryName.name_length] = '\0';
   ScopedLocalRef<jstring> entryNameString(env, env->NewStringUTF(entryNameCString.get()));
 
-  return newZipEntry(env, data, entryNameString.get(), entryName.name_length);
+  return newZipEntry(env, data, entryNameString.get());
 }
 
 static jobject StrictJarFile_nativeFindEntry(JNIEnv* env, jobject, jlong nativeHandle,
@@ -147,12 +141,12 @@
 
   ZipEntry data;
   const int32_t error = FindEntry(reinterpret_cast<ZipArchiveHandle>(nativeHandle),
-                                  entryNameChars.c_str(), &data);
+                                  ZipEntryName(entryNameChars.c_str()), &data);
   if (error) {
     return NULL;
   }
 
-  return newZipEntry(env, data, entryName, entryNameChars.size());
+  return newZipEntry(env, data, entryName);
 }
 
 static void StrictJarFile_nativeClose(JNIEnv*, jobject, jlong nativeHandle) {
diff --git a/luni/src/main/native/libcore_io_Posix.cpp b/luni/src/main/native/libcore_io_Posix.cpp
index e8e8efb..6808dd6 100644
--- a/luni/src/main/native/libcore_io_Posix.cpp
+++ b/luni/src/main/native/libcore_io_Posix.cpp
@@ -873,8 +873,9 @@
     return 0;
   }
   return static_cast<jint>(owner);
+#elif defined(__BIONIC__)
+  return gettid();
 #else
-  // Neither bionic nor glibc exposes gettid(2).
   return syscall(__NR_gettid);
 #endif
 }
diff --git a/luni/src/test/java/libcore/java/security/cert/CertificateFactoryTest.java b/luni/src/test/java/libcore/java/security/cert/CertificateFactoryTest.java
index e2f21e8..30185d1 100644
--- a/luni/src/test/java/libcore/java/security/cert/CertificateFactoryTest.java
+++ b/luni/src/test/java/libcore/java/security/cert/CertificateFactoryTest.java
@@ -17,10 +17,10 @@
 package libcore.java.security.cert;
 
 import com.android.org.bouncycastle.asn1.x509.BasicConstraints;
+import com.android.org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
 import com.android.org.bouncycastle.asn1.x509.X509Extensions;
 import com.android.org.bouncycastle.x509.X509V3CertificateGenerator;
 import com.android.org.bouncycastle.x509.extension.AuthorityKeyIdentifierStructure;
-import com.android.org.bouncycastle.x509.extension.SubjectKeyIdentifierStructure;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
@@ -571,7 +571,7 @@
         }
 
         certGen.addExtension(X509Extensions.SubjectKeyIdentifier, false,
-                new SubjectKeyIdentifierStructure(keyPair.getPublic()));
+                SubjectKeyIdentifier.getInstance(keyPair.getPublic().getEncoded()));
         certGen.addExtension(X509Extensions.BasicConstraints, true, basicConstraints);
 
         X509Certificate cert = certGen.generate(caKey);
diff --git a/luni/src/test/java/libcore/javax/net/ssl/DefaultHostnameVerifierTest.java b/luni/src/test/java/libcore/javax/net/ssl/DefaultHostnameVerifierTest.java
index e1c9fe3..71ccea4 100644
--- a/luni/src/test/java/libcore/javax/net/ssl/DefaultHostnameVerifierTest.java
+++ b/luni/src/test/java/libcore/javax/net/ssl/DefaultHostnameVerifierTest.java
@@ -129,6 +129,17 @@
         assertFalse(verifier.verifyHostName("a.b.c.d", "*.c.d"));
     }
 
+    public void testWildcardsRejectedForSingleLabelPatterns() {
+        assertFalse(verifier.verifyHostName("d", "*"));
+        assertFalse(verifier.verifyHostName("d.", "*."));
+        assertFalse(verifier.verifyHostName("d", "d*"));
+        assertFalse(verifier.verifyHostName("d.", "d*."));
+        assertFalse(verifier.verifyHostName("d", "*d"));
+        assertFalse(verifier.verifyHostName("d.", "*d."));
+        assertFalse(verifier.verifyHostName("ddd", "d*d"));
+        assertFalse(verifier.verifyHostName("ddd.", "d*d."));
+    }
+
     public void testVerifyHostName() {
         assertTrue(verifier.verifyHostName("a.b.c.d", "a.b.c.d"));
         assertTrue(verifier.verifyHostName("a.b.c.d", "*.b.c.d"));
@@ -142,6 +153,33 @@
         assertFalse(verifier.verifyHostName("imap.google.com", "a*.google.com"));
         assertFalse(verifier.verifyHostName("imap.google.com", "ix*.google.com"));
         assertTrue(verifier.verifyHostName("imap.google.com", "iMap.Google.Com"));
+        assertTrue(verifier.verifyHostName("weird", "weird"));
+        assertFalse(verifier.verifyHostName("weird", "weird*"));
+        assertFalse(verifier.verifyHostName("weird", "*weird"));
+        assertFalse(verifier.verifyHostName("weird", "weird."));
+        assertFalse(verifier.verifyHostName("weird", "weird*."));
+        assertFalse(verifier.verifyHostName("weird", "weird.*"));
+    }
+
+    public void testVerifyAbsoluteHostName() {
+        assertTrue(verifier.verifyHostName("a.b.c.d.", "a.b.c.d"));
+        assertTrue(verifier.verifyHostName("a.b.c.d.", "*.b.c.d"));
+        assertFalse(verifier.verifyHostName("a.b.c.d.", "*.*.c.d"));
+        assertTrue(verifier.verifyHostName("imap.google.com.", "imap.google.com"));
+        assertFalse(verifier.verifyHostName("imap2.google.com.", "imap.google.com"));
+        assertTrue(verifier.verifyHostName("imap.google.com.", "*.google.com"));
+        assertTrue(verifier.verifyHostName("imap2.google.com.", "*.google.com"));
+        assertFalse(verifier.verifyHostName("imap.google.com.", "*.googl.com"));
+        assertFalse(verifier.verifyHostName("imap2.google2.com.", "*.google3.com"));
+        assertFalse(verifier.verifyHostName("imap.google.com.", "a*.google.com"));
+        assertFalse(verifier.verifyHostName("imap.google.com.", "ix*.google.com"));
+        assertTrue(verifier.verifyHostName("imap.google.com.", "iMap.Google.Com"));
+        assertTrue(verifier.verifyHostName("weird.", "weird"));
+        assertTrue(verifier.verifyHostName("weird.", "weird*"));
+        assertTrue(verifier.verifyHostName("weird.", "*weird"));
+        assertTrue(verifier.verifyHostName("weird.", "weird."));
+        assertTrue(verifier.verifyHostName("weird.", "weird*."));
+        assertFalse(verifier.verifyHostName("weird.", "weird.*"));
     }
 
     public void testSubjectOnlyCert() throws Exception {