Improve float to integral conversion.

Change-Id: I1597083cb2c04084ce825fe2e3c753fde8309cd8
diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h
index 8b58cb3..fff7b71 100644
--- a/runtime/entrypoints/entrypoint_utils.h
+++ b/runtime/entrypoints/entrypoint_utils.h
@@ -16,7 +16,8 @@
 
 #ifndef ART_RUNTIME_ENTRYPOINTS_ENTRYPOINT_UTILS_H_
 #define ART_RUNTIME_ENTRYPOINTS_ENTRYPOINT_UTILS_H_
-#include "object_utils.h"
+
+#include "base/macros.h"
 #include "class_linker.h"
 #include "common_throws.h"
 #include "dex_file.h"
@@ -27,6 +28,7 @@
 #include "mirror/array.h"
 #include "mirror/class-inl.h"
 #include "mirror/throwable.h"
+#include "object_utils.h"
 
 #include "thread.h"
 
@@ -416,6 +418,23 @@
   return reinterpret_cast<void*>(art_jni_dlsym_lookup_stub);
 }
 
+template <typename INT_TYPE, typename FLOAT_TYPE>
+static inline INT_TYPE art_float_to_integral(FLOAT_TYPE f) {
+  const INT_TYPE kMaxInt = static_cast<INT_TYPE>(std::numeric_limits<INT_TYPE>::max());
+  const INT_TYPE kMinInt = static_cast<INT_TYPE>(std::numeric_limits<INT_TYPE>::min());
+  const FLOAT_TYPE kMaxIntAsFloat = static_cast<FLOAT_TYPE>(kMaxInt);
+  const FLOAT_TYPE kMinIntAsFloat = static_cast<FLOAT_TYPE>(kMinInt);
+  if (LIKELY(f > kMinIntAsFloat)) {
+     if (LIKELY(f < kMaxIntAsFloat)) {
+       return static_cast<INT_TYPE>(f);
+     } else {
+       return kMaxInt;
+     }
+  } else {
+    return (f != f) ? 0 : kMinInt;  // f != f implies NaN
+  }
+}
+
 }  // namespace art
 
 #endif  // ART_RUNTIME_ENTRYPOINTS_ENTRYPOINT_UTILS_H_
diff --git a/runtime/entrypoints/math_entrypoints.cc b/runtime/entrypoints/math_entrypoints.cc
index 31d13c8..b839b63 100644
--- a/runtime/entrypoints/math_entrypoints.cc
+++ b/runtime/entrypoints/math_entrypoints.cc
@@ -16,6 +16,8 @@
 
 #include "math_entrypoints.h"
 
+#include "entrypoint_utils.h"
+
 namespace art {
 
 extern "C" double art_l2d(int64_t l) {
@@ -31,59 +33,19 @@
  * target doesn't support this normally, use these.
  */
 extern "C" int64_t art_d2l(double d) {
-  static const double kMaxLong = static_cast<double>(static_cast<int64_t>(0x7fffffffffffffffULL));
-  static const double kMinLong = static_cast<double>(static_cast<int64_t>(0x8000000000000000ULL));
-  if (d >= kMaxLong) {
-    return static_cast<int64_t>(0x7fffffffffffffffULL);
-  } else if (d <= kMinLong) {
-    return static_cast<int64_t>(0x8000000000000000ULL);
-  } else if (d != d)  {  // NaN case
-    return 0;
-  } else {
-    return static_cast<int64_t>(d);
-  }
+  return art_float_to_integral<int64_t, double>(d);
 }
 
 extern "C" int64_t art_f2l(float f) {
-  static const float kMaxLong = static_cast<float>(static_cast<int64_t>(0x7fffffffffffffffULL));
-  static const float kMinLong = static_cast<float>(static_cast<int64_t>(0x8000000000000000ULL));
-  if (f >= kMaxLong) {
-    return static_cast<int64_t>(0x7fffffffffffffffULL);
-  } else if (f <= kMinLong) {
-    return static_cast<int64_t>(0x8000000000000000ULL);
-  } else if (f != f) {  // NaN case
-    return 0;
-  } else {
-    return static_cast<int64_t>(f);
-  }
+  return art_float_to_integral<int64_t, float>(f);
 }
 
 extern "C" int32_t art_d2i(double d) {
-  static const double kMaxInt = static_cast<double>(static_cast<int32_t>(0x7fffffffUL));
-  static const double kMinInt = static_cast<double>(static_cast<int32_t>(0x80000000UL));
-  if (d >= kMaxInt) {
-    return static_cast<int32_t>(0x7fffffffUL);
-  } else if (d <= kMinInt) {
-    return static_cast<int32_t>(0x80000000UL);
-  } else if (d != d)  {  // NaN case
-    return 0;
-  } else {
-    return static_cast<int32_t>(d);
-  }
+  return art_float_to_integral<int32_t, double>(d);
 }
 
 extern "C" int32_t art_f2i(float f) {
-  static const float kMaxInt = static_cast<float>(static_cast<int32_t>(0x7fffffffUL));
-  static const float kMinInt = static_cast<float>(static_cast<int32_t>(0x80000000UL));
-  if (f >= kMaxInt) {
-    return static_cast<int32_t>(0x7fffffffUL);
-  } else if (f <= kMinInt) {
-    return static_cast<int32_t>(0x80000000UL);
-  } else if (f != f) {  // NaN case
-    return 0;
-  } else {
-    return static_cast<int32_t>(f);
-  }
+  return art_float_to_integral<int32_t, float>(f);
 }
 
 }  // namespace art
diff --git a/runtime/interpreter/interpreter_goto_table_impl.cc b/runtime/interpreter/interpreter_goto_table_impl.cc
index b55c2c2..d70b80e 100644
--- a/runtime/interpreter/interpreter_goto_table_impl.cc
+++ b/runtime/interpreter/interpreter_goto_table_impl.cc
@@ -1460,16 +1460,7 @@
 
   HANDLE_INSTRUCTION_START(FLOAT_TO_INT) {
     float val = shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data));
-    int32_t result;
-    if (val != val) {
-      result = 0;
-    } else if (val > static_cast<float>(kMaxInt)) {
-      result = kMaxInt;
-    } else if (val < static_cast<float>(kMinInt)) {
-      result = kMinInt;
-    } else {
-      result = val;
-    }
+    int32_t result = art_float_to_integral<int32_t, float>(val);
     shadow_frame.SetVReg(inst->VRegA_12x(inst_data), result);
     ADVANCE(1);
   }
@@ -1477,16 +1468,7 @@
 
   HANDLE_INSTRUCTION_START(FLOAT_TO_LONG) {
     float val = shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data));
-    int64_t result;
-    if (val != val) {
-      result = 0;
-    } else if (val > static_cast<float>(kMaxLong)) {
-      result = kMaxLong;
-    } else if (val < static_cast<float>(kMinLong)) {
-      result = kMinLong;
-    } else {
-      result = val;
-    }
+    int64_t result = art_float_to_integral<int64_t, float>(val);
     shadow_frame.SetVRegLong(inst->VRegA_12x(inst_data), result);
     ADVANCE(1);
   }
@@ -1499,16 +1481,7 @@
 
   HANDLE_INSTRUCTION_START(DOUBLE_TO_INT) {
     double val = shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data));
-    int32_t result;
-    if (val != val) {
-      result = 0;
-    } else if (val > static_cast<double>(kMaxInt)) {
-      result = kMaxInt;
-    } else if (val < static_cast<double>(kMinInt)) {
-      result = kMinInt;
-    } else {
-      result = val;
-    }
+    int32_t result = art_float_to_integral<int32_t, double>(val);
     shadow_frame.SetVReg(inst->VRegA_12x(inst_data), result);
     ADVANCE(1);
   }
@@ -1516,16 +1489,7 @@
 
   HANDLE_INSTRUCTION_START(DOUBLE_TO_LONG) {
     double val = shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data));
-    int64_t result;
-    if (val != val) {
-      result = 0;
-    } else if (val > static_cast<double>(kMaxLong)) {
-      result = kMaxLong;
-    } else if (val < static_cast<double>(kMinLong)) {
-      result = kMinLong;
-    } else {
-      result = val;
-    }
+    int64_t result = art_float_to_integral<int64_t, double>(val);
     shadow_frame.SetVRegLong(inst->VRegA_12x(inst_data), result);
     ADVANCE(1);
   }
diff --git a/runtime/interpreter/interpreter_switch_impl.cc b/runtime/interpreter/interpreter_switch_impl.cc
index b2e480f..d49807c 100644
--- a/runtime/interpreter/interpreter_switch_impl.cc
+++ b/runtime/interpreter/interpreter_switch_impl.cc
@@ -1361,47 +1361,44 @@
         break;
       case Instruction::INT_TO_LONG:
         PREAMBLE();
-        shadow_frame.SetVRegLong(inst->VRegA_12x(inst_data), shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
+        shadow_frame.SetVRegLong(inst->VRegA_12x(inst_data),
+                                 shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
         inst = inst->Next_1xx();
         break;
       case Instruction::INT_TO_FLOAT:
         PREAMBLE();
-        shadow_frame.SetVRegFloat(inst->VRegA_12x(inst_data), shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
+        shadow_frame.SetVRegFloat(inst->VRegA_12x(inst_data),
+                                  shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
         inst = inst->Next_1xx();
         break;
       case Instruction::INT_TO_DOUBLE:
         PREAMBLE();
-        shadow_frame.SetVRegDouble(inst->VRegA_12x(inst_data), shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
+        shadow_frame.SetVRegDouble(inst->VRegA_12x(inst_data),
+                                   shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
         inst = inst->Next_1xx();
         break;
       case Instruction::LONG_TO_INT:
         PREAMBLE();
-        shadow_frame.SetVReg(inst->VRegA_12x(inst_data), shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
+        shadow_frame.SetVReg(inst->VRegA_12x(inst_data),
+                             shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
         inst = inst->Next_1xx();
         break;
       case Instruction::LONG_TO_FLOAT:
         PREAMBLE();
-        shadow_frame.SetVRegFloat(inst->VRegA_12x(inst_data), shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
+        shadow_frame.SetVRegFloat(inst->VRegA_12x(inst_data),
+                                  shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
         inst = inst->Next_1xx();
         break;
       case Instruction::LONG_TO_DOUBLE:
         PREAMBLE();
-        shadow_frame.SetVRegDouble(inst->VRegA_12x(inst_data), shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
+        shadow_frame.SetVRegDouble(inst->VRegA_12x(inst_data),
+                                   shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
         inst = inst->Next_1xx();
         break;
       case Instruction::FLOAT_TO_INT: {
         PREAMBLE();
         float val = shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data));
-        int32_t result;
-        if (val != val) {
-          result = 0;
-        } else if (val > static_cast<float>(kMaxInt)) {
-          result = kMaxInt;
-        } else if (val < static_cast<float>(kMinInt)) {
-          result = kMinInt;
-        } else {
-          result = val;
-        }
+        int32_t result = art_float_to_integral<int32_t, float>(val);
         shadow_frame.SetVReg(inst->VRegA_12x(inst_data), result);
         inst = inst->Next_1xx();
         break;
@@ -1409,38 +1406,21 @@
       case Instruction::FLOAT_TO_LONG: {
         PREAMBLE();
         float val = shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data));
-        int64_t result;
-        if (val != val) {
-          result = 0;
-        } else if (val > static_cast<float>(kMaxLong)) {
-          result = kMaxLong;
-        } else if (val < static_cast<float>(kMinLong)) {
-          result = kMinLong;
-        } else {
-          result = val;
-        }
+        int64_t result = art_float_to_integral<int64_t, float>(val);
         shadow_frame.SetVRegLong(inst->VRegA_12x(inst_data), result);
         inst = inst->Next_1xx();
         break;
       }
       case Instruction::FLOAT_TO_DOUBLE:
         PREAMBLE();
-        shadow_frame.SetVRegDouble(inst->VRegA_12x(inst_data), shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data)));
+        shadow_frame.SetVRegDouble(inst->VRegA_12x(inst_data),
+                                   shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data)));
         inst = inst->Next_1xx();
         break;
       case Instruction::DOUBLE_TO_INT: {
         PREAMBLE();
         double val = shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data));
-        int32_t result;
-        if (val != val) {
-          result = 0;
-        } else if (val > static_cast<double>(kMaxInt)) {
-          result = kMaxInt;
-        } else if (val < static_cast<double>(kMinInt)) {
-          result = kMinInt;
-        } else {
-          result = val;
-        }
+        int32_t result = art_float_to_integral<int32_t, double>(val);
         shadow_frame.SetVReg(inst->VRegA_12x(inst_data), result);
         inst = inst->Next_1xx();
         break;
@@ -1448,23 +1428,15 @@
       case Instruction::DOUBLE_TO_LONG: {
         PREAMBLE();
         double val = shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data));
-        int64_t result;
-        if (val != val) {
-          result = 0;
-        } else if (val > static_cast<double>(kMaxLong)) {
-          result = kMaxLong;
-        } else if (val < static_cast<double>(kMinLong)) {
-          result = kMinLong;
-        } else {
-          result = val;
-        }
+        int64_t result = art_float_to_integral<int64_t, double>(val);
         shadow_frame.SetVRegLong(inst->VRegA_12x(inst_data), result);
         inst = inst->Next_1xx();
         break;
       }
       case Instruction::DOUBLE_TO_FLOAT:
         PREAMBLE();
-        shadow_frame.SetVRegFloat(inst->VRegA_12x(inst_data), shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data)));
+        shadow_frame.SetVRegFloat(inst->VRegA_12x(inst_data),
+                                  shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data)));
         inst = inst->Next_1xx();
         break;
       case Instruction::INT_TO_BYTE: