diff options
author | Ian Rogers <irogers@google.com> | 2013-09-20 17:36:02 -0700 |
---|---|---|
committer | Ian Rogers <irogers@google.com> | 2013-09-20 18:47:39 -0700 |
commit | 450dcb56ecbf6f729401e753f0a27e4170177ddd (patch) | |
tree | f596d57c5f6fbdc90b3dc68a2008e38ee48e2882 /runtime | |
parent | 810b1d704f2db0d935bf5dddae3545f79cabd435 (diff) | |
download | art-450dcb56ecbf6f729401e753f0a27e4170177ddd.zip art-450dcb56ecbf6f729401e753f0a27e4170177ddd.tar.gz art-450dcb56ecbf6f729401e753f0a27e4170177ddd.tar.bz2 |
Improve float to integral conversion.
Change-Id: I1597083cb2c04084ce825fe2e3c753fde8309cd8
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/entrypoints/entrypoint_utils.h | 21 | ||||
-rw-r--r-- | runtime/entrypoints/math_entrypoints.cc | 50 | ||||
-rw-r--r-- | runtime/interpreter/interpreter_goto_table_impl.cc | 44 | ||||
-rw-r--r-- | runtime/interpreter/interpreter_switch_impl.cc | 68 |
4 files changed, 50 insertions, 133 deletions
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 @@ static inline void* GetJniDlsymLookupStub() { 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 @@ extern "C" float art_l2f(int64_t l) { * 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 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem* 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 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem* 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 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem* 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 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem* 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 @@ static JValue ExecuteSwitchImpl(Thread* self, MethodHelper& mh, const DexFile::C 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 @@ static JValue ExecuteSwitchImpl(Thread* self, MethodHelper& mh, const DexFile::C 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 @@ static JValue ExecuteSwitchImpl(Thread* self, MethodHelper& mh, const DexFile::C 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: |