[builtins] Introduce proper base::ieee754::log.

This switches Math.log to use an fdlibm based version of log, imported
as base::ieee754::log, and use that consistently everywhere, i.e. change
the Float64Log TurboFan operators on Intel to use the C++ implementation
as well (same for Crankshaft).

R=yangguo@chromium.org
BUG=v8:5065,v8:5086

Review-Url: https://codereview.chromium.org/2053893003
Cr-Commit-Position: refs/heads/master@{#36880}
This commit is contained in:
bmeurer 2016-06-09 22:51:58 -07:00 committed by Commit bot
parent e5760c0808
commit d0c7775d7c
48 changed files with 356 additions and 177 deletions

View File

@ -1898,6 +1898,8 @@ v8_source_set("v8_libbase") {
"src/base/functional.cc",
"src/base/functional.h",
"src/base/hashmap.h",
"src/base/ieee754.cc",
"src/base/ieee754.h",
"src/base/iterator.h",
"src/base/lazy-instance.h",
"src/base/logging.cc",

View File

@ -39,6 +39,7 @@
#include "src/api.h"
#include "src/base/cpu.h"
#include "src/base/functional.h"
#include "src/base/ieee754.h"
#include "src/base/lazy-instance.h"
#include "src/base/platform/platform.h"
#include "src/base/utils/random-number-generator.h"
@ -1027,7 +1028,7 @@ void ExternalReference::InitializeMathExpData() {
// 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) / std::log(2.0);
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);
@ -1647,13 +1648,9 @@ ExternalReference ExternalReference::address_of_regexp_stack_memory_size(
#endif // V8_INTERPRETED_REGEXP
ExternalReference ExternalReference::math_log_double_function(
Isolate* isolate) {
typedef double (*d2d)(double x);
return ExternalReference(Redirect(isolate,
FUNCTION_ADDR(static_cast<d2d>(std::log)),
BUILTIN_FP_CALL));
ExternalReference ExternalReference::ieee754_log_function(Isolate* isolate) {
return ExternalReference(
Redirect(isolate, FUNCTION_ADDR(base::ieee754::log), BUILTIN_FP_CALL));
}

View File

@ -1035,7 +1035,8 @@ class ExternalReference BASE_EMBEDDED {
static ExternalReference address_of_the_hole_nan();
static ExternalReference address_of_uint32_bias();
static ExternalReference math_log_double_function(Isolate* isolate);
// IEEE 754 functions.
static ExternalReference ieee754_log_function(Isolate* isolate);
static ExternalReference math_exp_constants(int constant_index);
static ExternalReference math_exp_log_table();

197
src/base/ieee754.cc Normal file
View File

@ -0,0 +1,197 @@
// The following is adapted from fdlibm (http://www.netlib.org/fdlibm).
//
// ====================================================
// 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.
// ====================================================
//
// The original source code covered by the above license above has been
// modified significantly by Google Inc.
// Copyright 2016 the V8 project authors. All rights reserved.
#include "src/base/ieee754.h"
#include <limits>
#include "src/base/build_config.h"
#include "src/base/macros.h"
namespace v8 {
namespace base {
namespace ieee754 {
namespace {
union Float64 {
double v;
uint64_t w;
struct {
#if V8_TARGET_LITTLE_ENDIAN
uint32_t lw;
uint32_t hw;
#else
uint32_t hw;
uint32_t lw;
#endif
} words;
};
// Extract the less significant 32-bit word from a double.
V8_INLINE uint32_t extractLowWord32(double v) {
Float64 f;
f.v = v;
return f.words.lw;
}
// Extract the most significant 32-bit word from a double.
V8_INLINE uint32_t extractHighWord32(double v) {
Float64 f;
f.v = v;
return f.words.hw;
}
// Insert the most significant 32-bit word into a double.
V8_INLINE double insertHighWord32(double v, uint32_t hw) {
Float64 f;
f.v = v;
f.words.hw = hw;
return f.v;
}
double const kLn2Hi = 6.93147180369123816490e-01; // 3fe62e42 fee00000
double const kLn2Lo = 1.90821492927058770002e-10; // 3dea39ef 35793c76
double const kTwo54 = 1.80143985094819840000e+16; // 43500000 00000000
double const kLg1 = 6.666666666666735130e-01; // 3FE55555 55555593
double const kLg2 = 3.999999999940941908e-01; // 3FD99999 9997FA04
double const kLg3 = 2.857142874366239149e-01; // 3FD24924 94229359
double const kLg4 = 2.222219843214978396e-01; // 3FCC71C5 1D8E78AF
double const kLg5 = 1.818357216161805012e-01; // 3FC74664 96CB03DE
double const kLg6 = 1.531383769920937332e-01; // 3FC39A09 D078C69F
double const kLg7 = 1.479819860511658591e-01; // 3FC2F112 DF3E5244
} // namespace
/* log(x)
* Return the logrithm of x
*
* Method :
* 1. Argument Reduction: find k and f such that
* x = 2^k * (1+f),
* where sqrt(2)/2 < 1+f < sqrt(2) .
*
* 2. Approximation of log(1+f).
* Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s)
* = 2s + 2/3 s**3 + 2/5 s**5 + .....,
* = 2s + s*R
* We use a special Reme algorithm on [0,0.1716] to generate
* a polynomial of degree 14 to approximate R The maximum error
* of this polynomial approximation is bounded by 2**-58.45. In
* other words,
* 2 4 6 8 10 12 14
* R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s +Lg6*s +Lg7*s
* (the values of Lg1 to Lg7 are listed in the program)
* and
* | 2 14 | -58.45
* | Lg1*s +...+Lg7*s - R(z) | <= 2
* | |
* Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2.
* In order to guarantee error in log below 1ulp, we compute log
* by
* log(1+f) = f - s*(f - R) (if f is not too large)
* log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy)
*
* 3. Finally, log(x) = k*ln2 + log(1+f).
* = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo)))
* Here ln2 is split into two floating point number:
* ln2_hi + ln2_lo,
* where n*ln2_hi is always exact for |n| < 2000.
*
* Special cases:
* log(x) is NaN with signal if x < 0 (including -INF) ;
* log(+INF) is +INF; log(0) is -INF with signal;
* log(NaN) is that NaN with no signal.
*
* Accuracy:
* according to an error analysis, the error is always less than
* 1 ulp (unit in the last place).
*
* Constants:
* The hexadecimal values are the intended ones for the following
* constants. The decimal values may be used, provided that the
* compiler will convert from decimal to binary accurately enough
* to produce the hexadecimal values shown.
*/
double log(double x) {
double hfsq, f, s, z, r, w, t1, t2, dk;
int32_t k = 0, i, j;
int32_t hx = extractHighWord32(x);
uint32_t lx = extractLowWord32(x);
if (hx < 0x00100000) { /* x < 2**-1022 */
if (((hx & 0x7fffffff) | lx) == 0) {
return -std::numeric_limits<double>::infinity();
}
if (hx < 0) {
return std::numeric_limits<double>::quiet_NaN();
}
k -= 54;
x *= kTwo54; /* subnormal number, scale up x */
hx = extractHighWord32(x);
}
if (hx >= 0x7ff00000) return x + x;
k += (hx >> 20) - 1023;
hx &= 0x000fffff;
i = (hx + 0x95f64) & 0x100000;
x = insertHighWord32(x, hx | (i ^ 0x3ff00000)); /* normalize x or x/2 */
k += (i >> 20);
f = x - 1.0;
if ((0x000fffff & (2 + hx)) < 3) { /* -2**-20 <= f < 2**-20 */
if (f == 0.0) {
if (k == 0) {
return 0.0;
} else {
dk = static_cast<double>(k);
return dk * kLn2Hi + dk * kLn2Lo;
}
}
r = f * f * (0.5 - 0.33333333333333333 * f);
if (k == 0) {
return f - r;
} else {
dk = static_cast<double>(k);
return dk * kLn2Hi - ((r - dk * kLn2Lo) - f);
}
}
s = f / (2.0 + f);
dk = static_cast<double>(k);
z = s * s;
i = hx - 0x6147a;
w = z * z;
j = 0x6b851 - hx;
t1 = w * (kLg2 + w * (kLg4 + w * kLg6));
t2 = z * (kLg1 + w * (kLg3 + w * (kLg5 + w * kLg7)));
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 * kLn2Hi - ((hfsq - (s * (hfsq + r) + dk * kLn2Lo)) - f);
}
} else {
if (k == 0) {
return f - s * (f - r);
} else {
return dk * kLn2Hi - ((s * (f - r) - dk * kLn2Lo) - f);
}
}
}
} // namespace ieee754
} // namespace base
} // namespace v8

19
src/base/ieee754.h Normal file
View File

@ -0,0 +1,19 @@
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_BASE_IEEE754_H_
#define V8_BASE_IEEE754_H_
namespace v8 {
namespace base {
namespace ieee754 {
// Returns the natural logarithm of |x|.
double log(double x);
} // namespace ieee754
} // namespace base
} // namespace v8
#endif // V8_BASE_IEEE754_H_

View File

@ -674,6 +674,19 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ add(i.OutputRegister(0), base, Operand(offset.offset()));
break;
}
case kIeee754Float64Log: {
// TODO(bmeurer): We should really get rid of this special instruction,
// and generate a CallAddress instruction instead.
FrameScope scope(masm(), StackFrame::MANUAL);
__ PrepareCallCFunction(0, 1, kScratchReg);
__ MovToFloatParameter(i.InputFloat64Register(0));
__ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 0,
1);
// Move the result in the double result register.
__ MovFromFloatResult(i.OutputFloat64Register());
DCHECK_EQ(LeaveCC, i.OutputSBit());
break;
}
case kArmAdd:
__ add(i.OutputRegister(), i.InputRegister(0), i.InputOperand2(1),
i.OutputSBit());
@ -998,19 +1011,6 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
DCHECK_EQ(LeaveCC, i.OutputSBit());
break;
}
case kArmVlogF64: {
// TODO(bmeurer): We should really get rid of this special instruction,
// and generate a CallAddress instruction instead.
FrameScope scope(masm(), StackFrame::MANUAL);
__ PrepareCallCFunction(0, 1, kScratchReg);
__ MovToFloatParameter(i.InputFloat64Register(0));
__ CallCFunction(ExternalReference::math_log_double_function(isolate()),
0, 1);
// Move the result in the double result register.
__ MovFromFloatResult(i.OutputFloat64Register());
DCHECK_EQ(LeaveCC, i.OutputSBit());
break;
}
case kArmVsqrtF64:
__ vsqrt(i.OutputFloat64Register(), i.InputFloat64Register(0));
break;

View File

@ -71,7 +71,6 @@ namespace compiler {
V(ArmVdivF64) \
V(ArmVmodF64) \
V(ArmVabsF64) \
V(ArmVlogF64) \
V(ArmVnegF64) \
V(ArmVsqrtF64) \
V(ArmVrintmF32) \

View File

@ -73,7 +73,6 @@ int InstructionScheduler::GetTargetInstructionFlags(
case kArmVdivF64:
case kArmVmodF64:
case kArmVabsF64:
case kArmVlogF64:
case kArmVnegF64:
case kArmVsqrtF64:
case kArmVrintmF32:

View File

@ -1395,7 +1395,8 @@ void InstructionSelector::VisitFloat64Abs(Node* node) {
void InstructionSelector::VisitFloat64Log(Node* node) {
ArmOperandGenerator g(this);
Emit(kArmVlogF64, g.DefineAsFixed(node, d0), g.UseFixed(node->InputAt(0), d0))
Emit(kIeee754Float64Log, g.DefineAsFixed(node, d0),
g.UseFixed(node->InputAt(0), d0))
->MarkAsCall();
}

View File

@ -792,6 +792,14 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ Add(i.OutputRegister(0), base, Operand(offset.offset()));
break;
}
case kIeee754Float64Log: {
FrameScope scope(masm(), StackFrame::MANUAL);
DCHECK(d0.is(i.InputDoubleRegister(0)));
DCHECK(d0.is(i.OutputDoubleRegister()));
__ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 0,
1);
break;
}
case kArm64Float32RoundDown:
__ Frintm(i.OutputFloat32Register(), i.InputFloat32Register(0));
break;
@ -1250,16 +1258,6 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kArm64Float64Abs:
__ Fabs(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
break;
case kArm64Float64Log: {
// TODO(dcarney): implement directly. See note in lithium-codegen-arm64.cc
FrameScope scope(masm(), StackFrame::MANUAL);
DCHECK(d0.is(i.InputDoubleRegister(0)));
DCHECK(d0.is(i.OutputDoubleRegister()));
// TODO(dcarney): make sure this saves all relevant registers.
__ CallCFunction(ExternalReference::math_log_double_function(isolate()),
0, 1);
break;
}
case kArm64Float64Neg:
__ Fneg(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
break;

View File

@ -104,7 +104,6 @@ namespace compiler {
V(Arm64Float64Max) \
V(Arm64Float64Min) \
V(Arm64Float64Abs) \
V(Arm64Float64Log) \
V(Arm64Float64Neg) \
V(Arm64Float64Sqrt) \
V(Arm64Float64RoundDown) \

View File

@ -97,7 +97,6 @@ int InstructionScheduler::GetTargetInstructionFlags(
case kArm64Float64Max:
case kArm64Float64Min:
case kArm64Float64Abs:
case kArm64Float64Log:
case kArm64Float64Neg:
case kArm64Float64Sqrt:
case kArm64Float64RoundDown:

View File

@ -1689,7 +1689,7 @@ void InstructionSelector::VisitFloat64Abs(Node* node) {
void InstructionSelector::VisitFloat64Log(Node* node) {
Arm64OperandGenerator g(this);
Emit(kArm64Float64Log, g.DefineAsFixed(node, d0),
Emit(kIeee754Float64Log, g.DefineAsFixed(node, d0),
g.UseFixed(node->InputAt(0), d0))
->MarkAsCall();
}

View File

@ -617,6 +617,19 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ lea(i.OutputRegister(), Operand(base, offset.offset()));
break;
}
case kIeee754Float64Log: {
// Pass one double as argument on the stack.
__ PrepareCallCFunction(2, eax);
__ movsd(Operand(esp, 0 * kDoubleSize), i.InputDoubleRegister(0));
__ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 2);
// Return value is in st(0) on ia32.
// Store it into the result register.
__ sub(esp, Immediate(kDoubleSize));
__ fstp_d(Operand(esp, 0));
__ movsd(i.OutputDoubleRegister(), Operand(esp, 0));
__ add(esp, Immediate(kDoubleSize));
break;
}
case kIA32Add:
if (HasImmediateInput(instr, 1)) {
__ add(i.InputOperand(0), i.InputImmediate(1));
@ -820,16 +833,6 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kIA32Popcnt:
__ Popcnt(i.OutputRegister(), i.InputOperand(0));
break;
case kX87Float64Log:
__ sub(esp, Immediate(kDoubleSize));
__ movsd(Operand(esp, 0), i.InputDoubleRegister(0));
__ fldln2();
__ fld_d(Operand(esp, 0));
__ fyl2x();
__ fstp_d(Operand(esp, 0));
__ movsd(i.OutputDoubleRegister(), Operand(esp, 0));
__ add(esp, Immediate(kDoubleSize));
break;
case kSSEFloat32Cmp:
__ ucomiss(i.InputDoubleRegister(0), i.InputOperand(1));
break;

View File

@ -43,7 +43,6 @@ namespace compiler {
V(IA32Lzcnt) \
V(IA32Tzcnt) \
V(IA32Popcnt) \
V(X87Float64Log) \
V(SSEFloat32Cmp) \
V(SSEFloat32Add) \
V(SSEFloat32Sub) \

View File

@ -46,7 +46,6 @@ int InstructionScheduler::GetTargetInstructionFlags(
case kIA32Tzcnt:
case kIA32Popcnt:
case kIA32Lea:
case kX87Float64Log:
case kSSEFloat32Cmp:
case kSSEFloat32Add:
case kSSEFloat32Sub:

View File

@ -1015,7 +1015,10 @@ void InstructionSelector::VisitFloat64Abs(Node* node) {
}
void InstructionSelector::VisitFloat64Log(Node* node) {
VisitRR(this, node, kX87Float64Log);
IA32OperandGenerator g(this);
Emit(kIeee754Float64Log, g.DefineSameAsFirst(node),
g.UseRegister(node->InputAt(0)))
->MarkAsCall();
}
void InstructionSelector::VisitFloat32Sqrt(Node* node) {

View File

@ -88,7 +88,8 @@ enum class RecordWriteMode { kValueIsMap, kValueIsPointer, kValueIsAny };
V(AtomicLoadWord32) \
V(AtomicStoreWord8) \
V(AtomicStoreWord16) \
V(AtomicStoreWord32)
V(AtomicStoreWord32) \
V(Ieee754Float64Log)
#define ARCH_OPCODE_LIST(V) \
COMMON_ARCH_OPCODE_LIST(V) \

View File

@ -224,6 +224,7 @@ int InstructionScheduler::GetInstructionFlags(const Instruction* instr) const {
case kArchStackSlot:
case kArchDebugBreak:
case kArchComment:
case kIeee754Float64Log:
return kNoOpcodeFlags;
case kArchStackPointer:

View File

@ -6,6 +6,7 @@
#include "src/base/bits.h"
#include "src/base/division-by-constant.h"
#include "src/base/ieee754.h"
#include "src/codegen.h"
#include "src/compiler/diamond.h"
#include "src/compiler/graph.h"
@ -384,7 +385,7 @@ Reduction MachineOperatorReducer::Reduce(Node* node) {
}
case IrOpcode::kFloat64Log: {
Float64Matcher m(node->InputAt(0));
if (m.HasValue()) return ReplaceFloat64(std::log(m.Value()));
if (m.HasValue()) return ReplaceFloat64(base::ieee754::log(m.Value()));
break;
}
case IrOpcode::kChangeFloat32ToFloat64: {

View File

@ -718,6 +718,18 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
Operand(offset.offset()));
break;
}
case kIeee754Float64Log: {
// TODO(bmeurer): We should really get rid of this special instruction,
// and generate a CallAddress instruction instead.
FrameScope scope(masm(), StackFrame::MANUAL);
__ PrepareCallCFunction(0, 1, kScratchReg);
__ MovToFloatParameter(i.InputDoubleRegister(0));
__ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 0,
1);
// Move the result in the double result register.
__ MovFromFloatResult(i.OutputDoubleRegister());
break;
}
case kMipsAdd:
__ Addu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break;
@ -1037,18 +1049,6 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kMipsAbsD:
__ abs_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
break;
case kMipsLogD: {
// TODO(bmeurer): We should really get rid of this special instruction,
// and generate a CallAddress instruction instead.
FrameScope scope(masm(), StackFrame::MANUAL);
__ PrepareCallCFunction(0, 1, kScratchReg);
__ MovToFloatParameter(i.InputDoubleRegister(0));
__ CallCFunction(ExternalReference::math_log_double_function(isolate()),
0, 1);
// Move the result in the double result register.
__ MovFromFloatResult(i.OutputDoubleRegister());
break;
}
case kMipsSqrtD: {
__ sqrt_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
break;

View File

@ -60,7 +60,6 @@ namespace compiler {
V(MipsDivD) \
V(MipsModD) \
V(MipsAbsD) \
V(MipsLogD) \
V(MipsSqrtD) \
V(MipsMaxD) \
V(MipsMinD) \

View File

@ -878,7 +878,8 @@ void InstructionSelector::VisitFloat64Abs(Node* node) {
void InstructionSelector::VisitFloat64Log(Node* node) {
MipsOperandGenerator g(this);
Emit(kMipsLogD, g.DefineAsFixed(node, f0), g.UseFixed(node->InputAt(0), f12))
Emit(kIeee754Float64Log, g.DefineAsFixed(node, f0),
g.UseFixed(node->InputAt(0), f12))
->MarkAsCall();
}

View File

@ -727,6 +727,18 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
Operand(offset.offset()));
break;
}
case kIeee754Float64Log: {
// TODO(bmeurer): We should really get rid of this special instruction,
// and generate a CallAddress instruction instead.
FrameScope scope(masm(), StackFrame::MANUAL);
__ PrepareCallCFunction(0, 1, kScratchReg);
__ MovToFloatParameter(i.InputDoubleRegister(0));
__ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 0,
1);
// Move the result in the double result register.
__ MovFromFloatResult(i.OutputDoubleRegister());
break;
}
case kMips64Add:
__ Addu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break;
@ -1185,18 +1197,6 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kMips64AbsD:
__ abs_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
break;
case kMips64LogD: {
// TODO(bmeurer): We should really get rid of this special instruction,
// and generate a CallAddress instruction instead.
FrameScope scope(masm(), StackFrame::MANUAL);
__ PrepareCallCFunction(0, 1, kScratchReg);
__ MovToFloatParameter(i.InputDoubleRegister(0));
__ CallCFunction(ExternalReference::math_log_double_function(isolate()),
0, 1);
// Move the result in the double result register.
__ MovFromFloatResult(i.OutputDoubleRegister());
break;
}
case kMips64SqrtD: {
__ sqrt_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
break;

View File

@ -75,7 +75,6 @@ namespace compiler {
V(Mips64DivD) \
V(Mips64ModD) \
V(Mips64AbsD) \
V(Mips64LogD) \
V(Mips64SqrtD) \
V(Mips64MaxD) \
V(Mips64MinD) \

View File

@ -1284,7 +1284,7 @@ void InstructionSelector::VisitFloat64Abs(Node* node) {
void InstructionSelector::VisitFloat64Log(Node* node) {
Mips64OperandGenerator g(this);
Emit(kMips64LogD, g.DefineAsFixed(node, f0),
Emit(kIeee754Float64Log, g.DefineAsFixed(node, f0),
g.UseFixed(node->InputAt(0), f12))
->MarkAsCall();
}

View File

@ -436,16 +436,15 @@ Condition FlagsConditionToCondition(FlagsCondition condition, ArchOpcode op) {
DCHECK_EQ(LeaveRC, i.OutputRCBit()); \
} while (0)
#define ASSEMBLE_FLOAT_LOG() \
do { \
FrameScope scope(masm(), StackFrame::MANUAL); \
__ PrepareCallCFunction(0, 1, kScratchReg); \
__ MovToFloatParameter(i.InputDoubleRegister(0)); \
__ CallCFunction(ExternalReference::math_log_double_function(isolate()), \
0, 1); \
__ MovFromFloatResult(i.OutputDoubleRegister()); \
DCHECK_EQ(LeaveRC, i.OutputRCBit()); \
#define ASSEMBLE_FLOAT_LOG() \
do { \
FrameScope scope(masm(), StackFrame::MANUAL); \
__ PrepareCallCFunction(0, 1, kScratchReg); \
__ MovToFloatParameter(i.InputDoubleRegister(0)); \
__ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 0, \
1); \
__ MovFromFloatResult(i.OutputDoubleRegister()); \
DCHECK_EQ(LeaveRC, i.OutputRCBit()); \
} while (0)
#define ASSEMBLE_FLOAT_MAX(scratch_reg) \

View File

@ -1225,8 +1225,8 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
FrameScope scope(masm(), StackFrame::MANUAL);
__ PrepareCallCFunction(0, 1, kScratchReg);
__ MovToFloatParameter(i.InputDoubleRegister(0));
__ CallCFunction(ExternalReference::math_log_double_function(isolate()),
0, 1);
__ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 0,
1);
// Move the result in the double result register.
__ MovFromFloatResult(i.OutputDoubleRegister());
break;

View File

@ -840,6 +840,10 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ leaq(i.OutputRegister(), Operand(base, offset.offset()));
break;
}
case kIeee754Float64Log:
__ PrepareCallCFunction(1);
__ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 1);
break;
case kX64Add32:
ASSEMBLE_BINOP(addl);
break;
@ -1008,16 +1012,6 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ Popcntl(i.OutputRegister(), i.InputOperand(0));
}
break;
case kX87Float64Log:
__ subq(rsp, Immediate(kDoubleSize));
__ Movsd(Operand(rsp, 0), i.InputDoubleRegister(0));
__ fldln2();
__ fld_d(Operand(rsp, 0));
__ fyl2x();
__ fstp_d(Operand(rsp, 0));
__ Movsd(i.OutputDoubleRegister(), Operand(rsp, 0));
__ addq(rsp, Immediate(kDoubleSize));
break;
case kSSEFloat32Cmp:
ASSEMBLE_SSE_BINOP(Ucomiss);
break;

View File

@ -56,7 +56,6 @@ namespace compiler {
V(X64Tzcnt32) \
V(X64Popcnt) \
V(X64Popcnt32) \
V(X87Float64Log) \
V(SSEFloat32Cmp) \
V(SSEFloat32Add) \
V(SSEFloat32Sub) \

View File

@ -58,7 +58,6 @@ int InstructionScheduler::GetTargetInstructionFlags(
case kX64Tzcnt32:
case kX64Popcnt:
case kX64Popcnt32:
case kX87Float64Log:
case kSSEFloat32Cmp:
case kSSEFloat32Add:
case kSSEFloat32Sub:

View File

@ -1356,7 +1356,10 @@ void InstructionSelector::VisitFloat64Abs(Node* node) {
}
void InstructionSelector::VisitFloat64Log(Node* node) {
VisitRR(this, node, kX87Float64Log);
X64OperandGenerator g(this);
Emit(kIeee754Float64Log, g.DefineAsFixed(node, xmm0),
g.UseFixed(node->InputAt(0), xmm0))
->MarkAsCall();
}
void InstructionSelector::VisitFloat64Sqrt(Node* node) {

View File

@ -3557,8 +3557,7 @@ void LCodeGen::DoMathExp(LMathExp* instr) {
void LCodeGen::DoMathLog(LMathLog* instr) {
__ PrepareCallCFunction(0, 1, scratch0());
__ MovToFloatParameter(ToDoubleRegister(instr->value()));
__ CallCFunction(ExternalReference::math_log_double_function(isolate()),
0, 1);
__ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 0, 1);
__ MovFromFloatResult(ToDoubleRegister(instr->result()));
}

View File

@ -3736,8 +3736,7 @@ void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
void LCodeGen::DoMathLog(LMathLog* instr) {
DCHECK(instr->IsMarkedAsCall());
DCHECK(ToDoubleRegister(instr->value()).is(d0));
__ CallCFunction(ExternalReference::math_log_double_function(isolate()),
0, 1);
__ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 0, 1);
DCHECK(ToDoubleRegister(instr->result()).Is(d0));
}

View File

@ -5,6 +5,7 @@
#include "src/crankshaft/hydrogen-instructions.h"
#include "src/base/bits.h"
#include "src/base/ieee754.h"
#include "src/base/safe_math.h"
#include "src/crankshaft/hydrogen-infer-representation.h"
#include "src/double.h"
@ -3425,7 +3426,7 @@ HInstruction* HUnaryMathOperation::New(Isolate* isolate, Zone* zone,
lazily_initialize_fast_exp(isolate);
return H_CONSTANT_DOUBLE(fast_exp(d, isolate));
case kMathLog:
return H_CONSTANT_DOUBLE(std::log(d));
return H_CONSTANT_DOUBLE(base::ieee754::log(d));
case kMathSqrt:
lazily_initialize_fast_sqrt(isolate);
return H_CONSTANT_DOUBLE(fast_sqrt(d, isolate));

View File

@ -3400,31 +3400,18 @@ void LCodeGen::DoPower(LPower* instr) {
void LCodeGen::DoMathLog(LMathLog* instr) {
DCHECK(instr->value()->Equals(instr->result()));
XMMRegister input_reg = ToDoubleRegister(instr->value());
XMMRegister xmm_scratch = double_scratch0();
Label positive, done, zero;
__ xorps(xmm_scratch, xmm_scratch);
__ ucomisd(input_reg, xmm_scratch);
__ j(above, &positive, Label::kNear);
__ j(not_carry, &zero, Label::kNear);
__ pcmpeqd(input_reg, input_reg);
__ jmp(&done, Label::kNear);
__ bind(&zero);
ExternalReference ninf =
ExternalReference::address_of_negative_infinity();
__ movsd(input_reg, Operand::StaticVariable(ninf));
__ jmp(&done, Label::kNear);
__ bind(&positive);
__ fldln2();
__ sub(Operand(esp), Immediate(kDoubleSize));
__ movsd(Operand(esp, 0), input_reg);
__ fld_d(Operand(esp, 0));
__ fyl2x();
XMMRegister input = ToDoubleRegister(instr->value());
XMMRegister result = ToDoubleRegister(instr->result());
// Pass one double as argument on the stack.
__ PrepareCallCFunction(2, eax);
__ movsd(Operand(esp, 0 * kDoubleSize), input);
__ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 2);
// Return value is in st(0) on ia32.
// Store it into the result register.
__ sub(esp, Immediate(kDoubleSize));
__ fstp_d(Operand(esp, 0));
__ movsd(input_reg, Operand(esp, 0));
__ add(Operand(esp), Immediate(kDoubleSize));
__ bind(&done);
__ movsd(result, Operand(esp, 0));
__ add(esp, Immediate(kDoubleSize));
}

View File

@ -3509,8 +3509,7 @@ void LCodeGen::DoMathExp(LMathExp* instr) {
void LCodeGen::DoMathLog(LMathLog* instr) {
__ PrepareCallCFunction(0, 1, scratch0());
__ MovToFloatParameter(ToDoubleRegister(instr->value()));
__ CallCFunction(ExternalReference::math_log_double_function(isolate()),
0, 1);
__ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 0, 1);
__ MovFromFloatResult(ToDoubleRegister(instr->result()));
}

View File

@ -3712,8 +3712,7 @@ void LCodeGen::DoMathExp(LMathExp* instr) {
void LCodeGen::DoMathLog(LMathLog* instr) {
__ PrepareCallCFunction(0, 1, scratch0());
__ MovToFloatParameter(ToDoubleRegister(instr->value()));
__ CallCFunction(ExternalReference::math_log_double_function(isolate()),
0, 1);
__ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 0, 1);
__ MovFromFloatResult(ToDoubleRegister(instr->result()));
}

View File

@ -3791,8 +3791,7 @@ void LCodeGen::DoMathExp(LMathExp* instr) {
void LCodeGen::DoMathLog(LMathLog* instr) {
__ PrepareCallCFunction(0, 1, scratch0());
__ MovToFloatParameter(ToDoubleRegister(instr->value()));
__ CallCFunction(ExternalReference::math_log_double_function(isolate()), 0,
1);
__ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 0, 1);
__ MovFromFloatResult(ToDoubleRegister(instr->result()));
}

View File

@ -3685,8 +3685,7 @@ void LCodeGen::DoMathExp(LMathExp* instr) {
void LCodeGen::DoMathLog(LMathLog* instr) {
__ PrepareCallCFunction(0, 1, scratch0());
__ MovToFloatParameter(ToDoubleRegister(instr->value()));
__ CallCFunction(ExternalReference::math_log_double_function(isolate()), 0,
1);
__ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 0, 1);
__ MovFromFloatResult(ToDoubleRegister(instr->result()));
}

View File

@ -3612,32 +3612,10 @@ void LCodeGen::DoMathExp(LMathExp* instr) {
void LCodeGen::DoMathLog(LMathLog* instr) {
DCHECK(instr->value()->Equals(instr->result()));
XMMRegister input_reg = ToDoubleRegister(instr->value());
XMMRegister xmm_scratch = double_scratch0();
Label positive, done, zero;
__ Xorpd(xmm_scratch, xmm_scratch);
__ Ucomisd(input_reg, xmm_scratch);
__ j(above, &positive, Label::kNear);
__ j(not_carry, &zero, Label::kNear);
__ Pcmpeqd(input_reg, input_reg);
__ jmp(&done, Label::kNear);
__ bind(&zero);
ExternalReference ninf =
ExternalReference::address_of_negative_infinity();
Operand ninf_operand = masm()->ExternalOperand(ninf);
__ Movsd(input_reg, ninf_operand);
__ jmp(&done, Label::kNear);
__ bind(&positive);
__ fldln2();
__ subp(rsp, Immediate(kDoubleSize));
__ Movsd(Operand(rsp, 0), input_reg);
__ fld_d(Operand(rsp, 0));
__ fyl2x();
__ fstp_d(Operand(rsp, 0));
__ Movsd(input_reg, Operand(rsp, 0));
__ addp(rsp, Immediate(kDoubleSize));
__ bind(&done);
DCHECK(ToDoubleRegister(instr->value()).is(xmm0));
DCHECK(ToDoubleRegister(instr->result()).is(xmm0));
__ PrepareCallCFunction(1);
__ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 1);
}

View File

@ -1155,8 +1155,9 @@ LInstruction* LChunkBuilder::DoMathAbs(HUnaryMathOperation* instr) {
LInstruction* LChunkBuilder::DoMathLog(HUnaryMathOperation* instr) {
DCHECK(instr->representation().IsDouble());
DCHECK(instr->value()->representation().IsDouble());
LOperand* input = UseRegisterAtStart(instr->value());
return MarkAsCall(DefineSameAsFirst(new(zone()) LMathLog(input)), instr);
LOperand* input = UseFixedDouble(instr->value(), xmm0);
return MarkAsCall(DefineFixedDouble(new (zone()) LMathLog(input), xmm0),
instr);
}

View File

@ -67,8 +67,8 @@ ExternalReferenceTable::ExternalReferenceTable(Isolate* isolate) {
"power_double_double_function");
Add(ExternalReference::power_double_int_function(isolate).address(),
"power_double_int_function");
Add(ExternalReference::math_log_double_function(isolate).address(),
"std::log");
Add(ExternalReference::ieee754_log_function(isolate).address(),
"base::ieee754::log");
Add(ExternalReference::store_buffer_top(isolate).address(),
"store_buffer_top");
Add(ExternalReference::address_of_the_hole_nan().address(), "the_hole_nan");

View File

@ -7,6 +7,7 @@
#include <stdint.h>
#include <memory>
#include "src/api.h"
#include "src/base/ieee754.h"
#include "src/base/utils/random-number-generator.h"
#include "src/frames-inl.h"
#include "src/heap/heap.h"
@ -27,7 +28,7 @@ intptr_t SamplingAllocationObserver::GetNextSampleInterval(uint64_t rate) {
return static_cast<intptr_t>(rate);
}
double u = random_->NextDouble();
double next = (-std::log(u)) * rate;
double next = (-base::ieee754::log(u)) * rate;
return next < kPointerSize
? kPointerSize
: (next > INT_MAX ? INT_MAX : static_cast<intptr_t>(next));

View File

@ -1680,6 +1680,8 @@
'base/functional.cc',
'base/functional.h',
'base/hashmap.h',
'base/ieee754.cc',
'base/ieee754.h',
'base/iterator.h',
'base/lazy-instance.h',
'base/logging.cc',

View File

@ -7,6 +7,7 @@
#include <limits>
#include "src/base/bits.h"
#include "src/base/ieee754.h"
#include "src/base/utils/random-number-generator.h"
#include "src/codegen.h"
#include "test/cctest/cctest.h"
@ -5507,7 +5508,7 @@ TEST(RunFloat64Log) {
CHECK_DOUBLE_EQ(0.0, m.Call(1.0));
CHECK_DOUBLE_EQ(std::numeric_limits<double>::infinity(),
m.Call(std::numeric_limits<double>::infinity()));
FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(std::log(*i), m.Call(*i)); }
FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(ieee754::log(*i), m.Call(*i)); }
}
static double two_30 = 1 << 30; // 2^30 is a smi boundary.

View File

@ -111,6 +111,7 @@ class ValueHelper {
-4.30175e-14f,
-5.27385e-15f,
-1.48084e-15f,
-2.220446049250313e-16f,
-1.05755e-19f,
-3.2995e-21f,
-1.67354e-23f,
@ -177,6 +178,7 @@ class ValueHelper {
static std::vector<double> float64_vector() {
static const double nan = std::numeric_limits<double>::quiet_NaN();
static const double values[] = {-2e66,
-2.220446049250313e-16,
-9223373136366403584.0,
-9223372036854775808.0, // INT64_MIN
-2147483649.5,

View File

@ -2,10 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/compiler/machine-operator-reducer.h"
#include "src/base/bits.h"
#include "src/base/division-by-constant.h"
#include "src/base/ieee754.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/machine-operator-reducer.h"
#include "src/compiler/typer.h"
#include "src/conversions-inl.h"
#include "test/unittests/compiler/graph-unittest.h"
@ -1408,7 +1409,7 @@ TEST_F(MachineOperatorReducerTest, Float64LogWithConstant) {
Reduce(graph()->NewNode(machine()->Float64Log(), Float64Constant(x)));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
IsFloat64Constant(NanSensitiveDoubleEq(std::log(x))));
IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::log(x))));
}
}