| Index: src/assembler.cc
 | 
| diff --git a/src/assembler.cc b/src/assembler.cc
 | 
| index 14b993abbbb4822075f824a569799f1b5c879e51..2332408f167e18d048ea72b2a0874877e5641d13 100644
 | 
| --- a/src/assembler.cc
 | 
| +++ b/src/assembler.cc
 | 
| @@ -177,6 +177,11 @@
 | 
|  static DoubleConstant double_constants;
 | 
|  
 | 
|  const char* const RelocInfo::kFillerCommentString = "DEOPTIMIZATION PADDING";
 | 
| +
 | 
| +static bool math_exp_data_initialized = false;
 | 
| +static base::Mutex* math_exp_data_mutex = NULL;
 | 
| +static double* math_exp_constants_array = NULL;
 | 
| +static double* math_exp_log_table_array = NULL;
 | 
|  
 | 
|  // -----------------------------------------------------------------------------
 | 
|  // Implementation of AssemblerBase
 | 
| @@ -1001,6 +1006,61 @@
 | 
|    double_constants.negative_infinity = -V8_INFINITY;
 | 
|    double_constants.uint32_bias =
 | 
|      static_cast<double>(static_cast<uint32_t>(0xFFFFFFFF)) + 1;
 | 
| +
 | 
| +  math_exp_data_mutex = new base::Mutex();
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void ExternalReference::InitializeMathExpData() {
 | 
| +  // Early return?
 | 
| +  if (math_exp_data_initialized) return;
 | 
| +
 | 
| +  base::LockGuard<base::Mutex> lock_guard(math_exp_data_mutex);
 | 
| +  if (!math_exp_data_initialized) {
 | 
| +    // If this is changed, generated code must be adapted too.
 | 
| +    const int kTableSizeBits = 11;
 | 
| +    const int kTableSize = 1 << kTableSizeBits;
 | 
| +    const double kTableSizeDouble = static_cast<double>(kTableSize);
 | 
| +
 | 
| +    math_exp_constants_array = new double[9];
 | 
| +    // Input values smaller than this always return 0.
 | 
| +    math_exp_constants_array[0] = -708.39641853226408;
 | 
| +    // Input values larger than this always return +Infinity.
 | 
| +    math_exp_constants_array[1] = 709.78271289338397;
 | 
| +    math_exp_constants_array[2] = V8_INFINITY;
 | 
| +    // The rest is black magic. Do not attempt to understand it. It is
 | 
| +    // loosely based on the "expd" function published at:
 | 
| +    // http://herumi.blogspot.com/2011/08/fast-double-precision-exponential.html
 | 
| +    const double constant3 = (1 << kTableSizeBits) / base::ieee754::log(2.0);
 | 
| +    math_exp_constants_array[3] = constant3;
 | 
| +    math_exp_constants_array[4] =
 | 
| +        static_cast<double>(static_cast<int64_t>(3) << 51);
 | 
| +    math_exp_constants_array[5] = 1 / constant3;
 | 
| +    math_exp_constants_array[6] = 3.0000000027955394;
 | 
| +    math_exp_constants_array[7] = 0.16666666685227835;
 | 
| +    math_exp_constants_array[8] = 1;
 | 
| +
 | 
| +    math_exp_log_table_array = new double[kTableSize];
 | 
| +    for (int i = 0; i < kTableSize; i++) {
 | 
| +      double value = std::pow(2, i / kTableSizeDouble);
 | 
| +      uint64_t bits = bit_cast<uint64_t, double>(value);
 | 
| +      bits &= (static_cast<uint64_t>(1) << 52) - 1;
 | 
| +      double mantissa = bit_cast<double, uint64_t>(bits);
 | 
| +      math_exp_log_table_array[i] = mantissa;
 | 
| +    }
 | 
| +
 | 
| +    math_exp_data_initialized = true;
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void ExternalReference::TearDownMathExpData() {
 | 
| +  delete[] math_exp_constants_array;
 | 
| +  math_exp_constants_array = NULL;
 | 
| +  delete[] math_exp_log_table_array;
 | 
| +  math_exp_log_table_array = NULL;
 | 
| +  delete math_exp_data_mutex;
 | 
| +  math_exp_data_mutex = NULL;
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -1293,7 +1353,7 @@
 | 
|  }
 | 
|  
 | 
|  static void f64_exp_wrapper(double* param) {
 | 
| -  WriteDoubleValue(param, base::ieee754::exp(ReadDoubleValue(param)));
 | 
| +  WriteDoubleValue(param, std::exp(ReadDoubleValue(param)));
 | 
|  }
 | 
|  
 | 
|  ExternalReference ExternalReference::f64_exp_wrapper_function(
 | 
| @@ -1568,11 +1628,6 @@
 | 
|        isolate, FUNCTION_ADDR(base::ieee754::atan2), BUILTIN_FP_FP_CALL));
 | 
|  }
 | 
|  
 | 
| -ExternalReference ExternalReference::ieee754_exp_function(Isolate* isolate) {
 | 
| -  return ExternalReference(
 | 
| -      Redirect(isolate, FUNCTION_ADDR(base::ieee754::exp), BUILTIN_FP_CALL));
 | 
| -}
 | 
| -
 | 
|  ExternalReference ExternalReference::ieee754_log_function(Isolate* isolate) {
 | 
|    return ExternalReference(
 | 
|        Redirect(isolate, FUNCTION_ADDR(base::ieee754::log), BUILTIN_FP_CALL));
 | 
| @@ -1592,6 +1647,19 @@
 | 
|    return ExternalReference(
 | 
|        Redirect(isolate, FUNCTION_ADDR(base::ieee754::log10), BUILTIN_FP_CALL));
 | 
|  }
 | 
| +
 | 
| +ExternalReference ExternalReference::math_exp_constants(int constant_index) {
 | 
| +  DCHECK(math_exp_data_initialized);
 | 
| +  return ExternalReference(
 | 
| +      reinterpret_cast<void*>(math_exp_constants_array + constant_index));
 | 
| +}
 | 
| +
 | 
| +
 | 
| +ExternalReference ExternalReference::math_exp_log_table() {
 | 
| +  DCHECK(math_exp_data_initialized);
 | 
| +  return ExternalReference(reinterpret_cast<void*>(math_exp_log_table_array));
 | 
| +}
 | 
| +
 | 
|  
 | 
|  ExternalReference ExternalReference::page_flags(Page* page) {
 | 
|    return ExternalReference(reinterpret_cast<Address>(page) +
 | 
| 
 |