Add generated code to calculate Math.log and to search Transcendental cache for logs. Implemented on all platforms.
Review URL: http://codereview.chromium.org/5437002 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5912 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
be20c55b3e
commit
66836efbba
@ -2290,6 +2290,7 @@ Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() {
|
||||
// Add more cases when necessary.
|
||||
case TranscendentalCache::SIN: return Runtime::kMath_sin;
|
||||
case TranscendentalCache::COS: return Runtime::kMath_cos;
|
||||
case TranscendentalCache::LOG: return Runtime::kMath_log;
|
||||
default:
|
||||
UNIMPLEMENTED();
|
||||
return Runtime::kAbort;
|
||||
|
@ -5750,6 +5750,20 @@ void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) {
|
||||
}
|
||||
|
||||
|
||||
void CodeGenerator::GenerateMathLog(ZoneList<Expression*>* args) {
|
||||
ASSERT_EQ(args->length(), 1);
|
||||
Load(args->at(0));
|
||||
if (CpuFeatures::IsSupported(VFP3)) {
|
||||
TranscendentalCacheStub stub(TranscendentalCache::LOG);
|
||||
frame_->SpillAllButCopyTOSToR0();
|
||||
frame_->CallStub(&stub, 1);
|
||||
} else {
|
||||
frame_->CallRuntime(Runtime::kMath_log, 1);
|
||||
}
|
||||
frame_->EmitPush(r0);
|
||||
}
|
||||
|
||||
|
||||
void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) {
|
||||
ASSERT(args->length() == 2);
|
||||
|
||||
|
@ -516,6 +516,7 @@ class CodeGenerator: public AstVisitor {
|
||||
void GenerateMathSin(ZoneList<Expression*>* args);
|
||||
void GenerateMathCos(ZoneList<Expression*>* args);
|
||||
void GenerateMathSqrt(ZoneList<Expression*>* args);
|
||||
void GenerateMathLog(ZoneList<Expression*>* args);
|
||||
|
||||
void GenerateIsRegExpEquivalent(ZoneList<Expression*>* args);
|
||||
|
||||
|
@ -2617,6 +2617,15 @@ void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) {
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) {
|
||||
// Load the argument on the stack and call the runtime function.
|
||||
ASSERT(args->length() == 1);
|
||||
VisitForStackValue(args->at(0));
|
||||
__ CallRuntime(Runtime::kMath_log, 1);
|
||||
context()->Plug(r0);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) {
|
||||
ASSERT(args->length() >= 2);
|
||||
|
||||
|
@ -1772,6 +1772,14 @@ void Assembler::fldz() {
|
||||
}
|
||||
|
||||
|
||||
void Assembler::fldln2() {
|
||||
EnsureSpace ensure_space(this);
|
||||
last_pc_ = pc_;
|
||||
EMIT(0xD9);
|
||||
EMIT(0xED);
|
||||
}
|
||||
|
||||
|
||||
void Assembler::fld_s(const Operand& adr) {
|
||||
EnsureSpace ensure_space(this);
|
||||
last_pc_ = pc_;
|
||||
@ -1902,6 +1910,14 @@ void Assembler::fsin() {
|
||||
}
|
||||
|
||||
|
||||
void Assembler::fyl2x() {
|
||||
EnsureSpace ensure_space(this);
|
||||
last_pc_ = pc_;
|
||||
EMIT(0xD9);
|
||||
EMIT(0xF1);
|
||||
}
|
||||
|
||||
|
||||
void Assembler::fadd(int i) {
|
||||
EnsureSpace ensure_space(this);
|
||||
last_pc_ = pc_;
|
||||
|
@ -720,6 +720,7 @@ class Assembler : public Malloced {
|
||||
void fld1();
|
||||
void fldz();
|
||||
void fldpi();
|
||||
void fldln2();
|
||||
|
||||
void fld_s(const Operand& adr);
|
||||
void fld_d(const Operand& adr);
|
||||
@ -744,6 +745,7 @@ class Assembler : public Malloced {
|
||||
void fchs();
|
||||
void fcos();
|
||||
void fsin();
|
||||
void fyl2x();
|
||||
|
||||
void fadd(int i);
|
||||
void fsub(int i);
|
||||
|
@ -1330,6 +1330,7 @@ Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() {
|
||||
// Add more cases when necessary.
|
||||
case TranscendentalCache::SIN: return Runtime::kMath_sin;
|
||||
case TranscendentalCache::COS: return Runtime::kMath_cos;
|
||||
case TranscendentalCache::LOG: return Runtime::kMath_log;
|
||||
default:
|
||||
UNIMPLEMENTED();
|
||||
return Runtime::kAbort;
|
||||
@ -1339,85 +1340,90 @@ Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() {
|
||||
|
||||
void TranscendentalCacheStub::GenerateOperation(MacroAssembler* masm) {
|
||||
// Only free register is edi.
|
||||
// Input value is on FP stack, and also in ebx/edx. Address of result
|
||||
// (a newly allocated HeapNumber) is in eax.
|
||||
NearLabel done;
|
||||
ASSERT(type_ == TranscendentalCache::SIN ||
|
||||
type_ == TranscendentalCache::COS);
|
||||
// More transcendental types can be added later.
|
||||
if (type_ == TranscendentalCache::SIN || type_ == TranscendentalCache::COS) {
|
||||
// Both fsin and fcos require arguments in the range +/-2^63 and
|
||||
// return NaN for infinities and NaN. They can share all code except
|
||||
// the actual fsin/fcos operation.
|
||||
NearLabel in_range;
|
||||
// If argument is outside the range -2^63..2^63, fsin/cos doesn't
|
||||
// work. We must reduce it to the appropriate range.
|
||||
__ mov(edi, edx);
|
||||
__ and_(Operand(edi), Immediate(0x7ff00000)); // Exponent only.
|
||||
int supported_exponent_limit =
|
||||
(63 + HeapNumber::kExponentBias) << HeapNumber::kExponentShift;
|
||||
__ cmp(Operand(edi), Immediate(supported_exponent_limit));
|
||||
__ j(below, &in_range, taken);
|
||||
// Check for infinity and NaN. Both return NaN for sin.
|
||||
__ cmp(Operand(edi), Immediate(0x7ff00000));
|
||||
NearLabel non_nan_result;
|
||||
__ j(not_equal, &non_nan_result, taken);
|
||||
// Input is +/-Infinity or NaN. Result is NaN.
|
||||
__ fstp(0);
|
||||
// NaN is represented by 0x7ff8000000000000.
|
||||
__ push(Immediate(0x7ff80000));
|
||||
__ push(Immediate(0));
|
||||
__ fld_d(Operand(esp, 0));
|
||||
__ add(Operand(esp), Immediate(2 * kPointerSize));
|
||||
__ jmp(&done);
|
||||
|
||||
// Both fsin and fcos require arguments in the range +/-2^63 and
|
||||
// return NaN for infinities and NaN. They can share all code except
|
||||
// the actual fsin/fcos operation.
|
||||
NearLabel in_range;
|
||||
// If argument is outside the range -2^63..2^63, fsin/cos doesn't
|
||||
// work. We must reduce it to the appropriate range.
|
||||
__ mov(edi, edx);
|
||||
__ and_(Operand(edi), Immediate(0x7ff00000)); // Exponent only.
|
||||
int supported_exponent_limit =
|
||||
(63 + HeapNumber::kExponentBias) << HeapNumber::kExponentShift;
|
||||
__ cmp(Operand(edi), Immediate(supported_exponent_limit));
|
||||
__ j(below, &in_range, taken);
|
||||
// Check for infinity and NaN. Both return NaN for sin.
|
||||
__ cmp(Operand(edi), Immediate(0x7ff00000));
|
||||
NearLabel non_nan_result;
|
||||
__ j(not_equal, &non_nan_result, taken);
|
||||
// Input is +/-Infinity or NaN. Result is NaN.
|
||||
__ fstp(0);
|
||||
// NaN is represented by 0x7ff8000000000000.
|
||||
__ push(Immediate(0x7ff80000));
|
||||
__ push(Immediate(0));
|
||||
__ fld_d(Operand(esp, 0));
|
||||
__ add(Operand(esp), Immediate(2 * kPointerSize));
|
||||
__ jmp(&done);
|
||||
__ bind(&non_nan_result);
|
||||
|
||||
__ bind(&non_nan_result);
|
||||
// Use fpmod to restrict argument to the range +/-2*PI.
|
||||
__ mov(edi, eax); // Save eax before using fnstsw_ax.
|
||||
__ fldpi();
|
||||
__ fadd(0);
|
||||
__ fld(1);
|
||||
// FPU Stack: input, 2*pi, input.
|
||||
{
|
||||
NearLabel no_exceptions;
|
||||
__ fwait();
|
||||
__ fnstsw_ax();
|
||||
// Clear if Illegal Operand or Zero Division exceptions are set.
|
||||
__ test(Operand(eax), Immediate(5));
|
||||
__ j(zero, &no_exceptions);
|
||||
__ fnclex();
|
||||
__ bind(&no_exceptions);
|
||||
}
|
||||
|
||||
// Use fpmod to restrict argument to the range +/-2*PI.
|
||||
__ mov(edi, eax); // Save eax before using fnstsw_ax.
|
||||
__ fldpi();
|
||||
__ fadd(0);
|
||||
__ fld(1);
|
||||
// FPU Stack: input, 2*pi, input.
|
||||
{
|
||||
NearLabel no_exceptions;
|
||||
__ fwait();
|
||||
__ fnstsw_ax();
|
||||
// Clear if Illegal Operand or Zero Division exceptions are set.
|
||||
__ test(Operand(eax), Immediate(5));
|
||||
__ j(zero, &no_exceptions);
|
||||
__ fnclex();
|
||||
__ bind(&no_exceptions);
|
||||
// Compute st(0) % st(1)
|
||||
{
|
||||
NearLabel partial_remainder_loop;
|
||||
__ bind(&partial_remainder_loop);
|
||||
__ fprem1();
|
||||
__ fwait();
|
||||
__ fnstsw_ax();
|
||||
__ test(Operand(eax), Immediate(0x400 /* C2 */));
|
||||
// If C2 is set, computation only has partial result. Loop to
|
||||
// continue computation.
|
||||
__ j(not_zero, &partial_remainder_loop);
|
||||
}
|
||||
// FPU Stack: input, 2*pi, input % 2*pi
|
||||
__ fstp(2);
|
||||
__ fstp(0);
|
||||
__ mov(eax, edi); // Restore eax (allocated HeapNumber pointer).
|
||||
|
||||
// FPU Stack: input % 2*pi
|
||||
__ bind(&in_range);
|
||||
switch (type_) {
|
||||
case TranscendentalCache::SIN:
|
||||
__ fsin();
|
||||
break;
|
||||
case TranscendentalCache::COS:
|
||||
__ fcos();
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
__ bind(&done);
|
||||
} else {
|
||||
ASSERT(type_ == TranscendentalCache::LOG);
|
||||
__ fldln2();
|
||||
__ fxch();
|
||||
__ fyl2x();
|
||||
}
|
||||
|
||||
// Compute st(0) % st(1)
|
||||
{
|
||||
NearLabel partial_remainder_loop;
|
||||
__ bind(&partial_remainder_loop);
|
||||
__ fprem1();
|
||||
__ fwait();
|
||||
__ fnstsw_ax();
|
||||
__ test(Operand(eax), Immediate(0x400 /* C2 */));
|
||||
// If C2 is set, computation only has partial result. Loop to
|
||||
// continue computation.
|
||||
__ j(not_zero, &partial_remainder_loop);
|
||||
}
|
||||
// FPU Stack: input, 2*pi, input % 2*pi
|
||||
__ fstp(2);
|
||||
__ fstp(0);
|
||||
__ mov(eax, edi); // Restore eax (allocated HeapNumber pointer).
|
||||
|
||||
// FPU Stack: input % 2*pi
|
||||
__ bind(&in_range);
|
||||
switch (type_) {
|
||||
case TranscendentalCache::SIN:
|
||||
__ fsin();
|
||||
break;
|
||||
case TranscendentalCache::COS:
|
||||
__ fcos();
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
__ bind(&done);
|
||||
}
|
||||
|
||||
|
||||
|
@ -7995,6 +7995,15 @@ void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) {
|
||||
}
|
||||
|
||||
|
||||
void CodeGenerator::GenerateMathLog(ZoneList<Expression*>* args) {
|
||||
ASSERT_EQ(args->length(), 1);
|
||||
Load(args->at(0));
|
||||
TranscendentalCacheStub stub(TranscendentalCache::LOG);
|
||||
Result result = frame_->CallStub(&stub, 1);
|
||||
frame_->Push(&result);
|
||||
}
|
||||
|
||||
|
||||
// Generates the Math.sqrt method. Please note - this function assumes that
|
||||
// the callsite has executed ToNumber on the argument.
|
||||
void CodeGenerator::GenerateMathSqrt(ZoneList<Expression*>* args) {
|
||||
|
@ -705,8 +705,9 @@ class CodeGenerator: public AstVisitor {
|
||||
void GenerateMathSin(ZoneList<Expression*>* args);
|
||||
void GenerateMathCos(ZoneList<Expression*>* args);
|
||||
void GenerateMathSqrt(ZoneList<Expression*>* args);
|
||||
void GenerateMathLog(ZoneList<Expression*>* args);
|
||||
|
||||
// Check whether two RegExps are equivalent
|
||||
// Check whether two RegExps are equivalent.
|
||||
void GenerateIsRegExpEquivalent(ZoneList<Expression*>* args);
|
||||
|
||||
void GenerateHasCachedArrayIndex(ZoneList<Expression*>* args);
|
||||
|
@ -733,7 +733,9 @@ int DisassemblerIA32::RegisterFPUInstruction(int escape_opcode,
|
||||
case 0xE4: mnem = "ftst"; break;
|
||||
case 0xE8: mnem = "fld1"; break;
|
||||
case 0xEB: mnem = "fldpi"; break;
|
||||
case 0xED: mnem = "fldln2"; break;
|
||||
case 0xEE: mnem = "fldz"; break;
|
||||
case 0xF1: mnem = "fyl2x"; break;
|
||||
case 0xF5: mnem = "fprem1"; break;
|
||||
case 0xF7: mnem = "fincstp"; break;
|
||||
case 0xF8: mnem = "fprem"; break;
|
||||
|
@ -2917,6 +2917,16 @@ void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) {
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) {
|
||||
// Load the argument on the stack and call the stub.
|
||||
TranscendentalCacheStub stub(TranscendentalCache::LOG);
|
||||
ASSERT(args->length() == 1);
|
||||
VisitForStackValue(args->at(0));
|
||||
__ CallStub(&stub);
|
||||
context()->Plug(eax);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) {
|
||||
// Load the argument on the stack and call the runtime function.
|
||||
ASSERT(args->length() == 1);
|
||||
|
@ -113,7 +113,7 @@ function MathFloor(x) {
|
||||
// ECMA 262 - 15.8.2.10
|
||||
function MathLog(x) {
|
||||
if (!IS_NUMBER(x)) x = ToNumber(x);
|
||||
return %Math_log(x);
|
||||
return %_MathLog(x);
|
||||
}
|
||||
|
||||
// ECMA 262 - 15.8.2.11
|
||||
|
@ -417,6 +417,7 @@ namespace internal {
|
||||
F(MathSin, 1, 1) \
|
||||
F(MathCos, 1, 1) \
|
||||
F(MathSqrt, 1, 1) \
|
||||
F(MathLog, 1, 1) \
|
||||
F(IsRegExpEquivalent, 2, 1) \
|
||||
F(HasCachedArrayIndex, 1, 1) \
|
||||
F(GetCachedArrayIndex, 1, 1) \
|
||||
|
@ -2217,6 +2217,14 @@ void Assembler::fldpi() {
|
||||
}
|
||||
|
||||
|
||||
void Assembler::fldln2() {
|
||||
EnsureSpace ensure_space(this);
|
||||
last_pc_ = pc_;
|
||||
emit(0xD9);
|
||||
emit(0xED);
|
||||
}
|
||||
|
||||
|
||||
void Assembler::fld_s(const Operand& adr) {
|
||||
EnsureSpace ensure_space(this);
|
||||
last_pc_ = pc_;
|
||||
@ -2358,6 +2366,14 @@ void Assembler::fsin() {
|
||||
}
|
||||
|
||||
|
||||
void Assembler::fyl2x() {
|
||||
EnsureSpace ensure_space(this);
|
||||
last_pc_ = pc_;
|
||||
emit(0xD9);
|
||||
emit(0xF1);
|
||||
}
|
||||
|
||||
|
||||
void Assembler::fadd(int i) {
|
||||
EnsureSpace ensure_space(this);
|
||||
last_pc_ = pc_;
|
||||
|
@ -1046,6 +1046,7 @@ class Assembler : public Malloced {
|
||||
void fld1();
|
||||
void fldz();
|
||||
void fldpi();
|
||||
void fldln2();
|
||||
|
||||
void fld_s(const Operand& adr);
|
||||
void fld_d(const Operand& adr);
|
||||
@ -1100,6 +1101,7 @@ class Assembler : public Malloced {
|
||||
|
||||
void fsin();
|
||||
void fcos();
|
||||
void fyl2x();
|
||||
|
||||
void frndint();
|
||||
|
||||
|
@ -1107,6 +1107,7 @@ Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() {
|
||||
// Add more cases when necessary.
|
||||
case TranscendentalCache::SIN: return Runtime::kMath_sin;
|
||||
case TranscendentalCache::COS: return Runtime::kMath_cos;
|
||||
case TranscendentalCache::LOG: return Runtime::kMath_log;
|
||||
default:
|
||||
UNIMPLEMENTED();
|
||||
return Runtime::kAbort;
|
||||
@ -1121,73 +1122,76 @@ void TranscendentalCacheStub::GenerateOperation(MacroAssembler* masm,
|
||||
// rcx: Pointer to cache entry. Must be preserved.
|
||||
// st(0): Input double
|
||||
Label done;
|
||||
ASSERT(type_ == TranscendentalCache::SIN ||
|
||||
type_ == TranscendentalCache::COS);
|
||||
// More transcendental types can be added later.
|
||||
if (type_ == TranscendentalCache::SIN || type_ == TranscendentalCache::COS) {
|
||||
// Both fsin and fcos require arguments in the range +/-2^63 and
|
||||
// return NaN for infinities and NaN. They can share all code except
|
||||
// the actual fsin/fcos operation.
|
||||
Label in_range;
|
||||
// If argument is outside the range -2^63..2^63, fsin/cos doesn't
|
||||
// work. We must reduce it to the appropriate range.
|
||||
__ movq(rdi, rbx);
|
||||
// Move exponent and sign bits to low bits.
|
||||
__ shr(rdi, Immediate(HeapNumber::kMantissaBits));
|
||||
// Remove sign bit.
|
||||
__ andl(rdi, Immediate((1 << HeapNumber::kExponentBits) - 1));
|
||||
int supported_exponent_limit = (63 + HeapNumber::kExponentBias);
|
||||
__ cmpl(rdi, Immediate(supported_exponent_limit));
|
||||
__ j(below, &in_range);
|
||||
// Check for infinity and NaN. Both return NaN for sin.
|
||||
__ cmpl(rdi, Immediate(0x7ff));
|
||||
__ j(equal, on_nan_result);
|
||||
|
||||
// Both fsin and fcos require arguments in the range +/-2^63 and
|
||||
// return NaN for infinities and NaN. They can share all code except
|
||||
// the actual fsin/fcos operation.
|
||||
Label in_range;
|
||||
// If argument is outside the range -2^63..2^63, fsin/cos doesn't
|
||||
// work. We must reduce it to the appropriate range.
|
||||
__ movq(rdi, rbx);
|
||||
// Move exponent and sign bits to low bits.
|
||||
__ shr(rdi, Immediate(HeapNumber::kMantissaBits));
|
||||
// Remove sign bit.
|
||||
__ andl(rdi, Immediate((1 << HeapNumber::kExponentBits) - 1));
|
||||
int supported_exponent_limit = (63 + HeapNumber::kExponentBias);
|
||||
__ cmpl(rdi, Immediate(supported_exponent_limit));
|
||||
__ j(below, &in_range);
|
||||
// Check for infinity and NaN. Both return NaN for sin.
|
||||
__ cmpl(rdi, Immediate(0x7ff));
|
||||
__ j(equal, on_nan_result);
|
||||
// Use fpmod to restrict argument to the range +/-2*PI.
|
||||
__ fldpi();
|
||||
__ fadd(0);
|
||||
__ fld(1);
|
||||
// FPU Stack: input, 2*pi, input.
|
||||
{
|
||||
Label no_exceptions;
|
||||
__ fwait();
|
||||
__ fnstsw_ax();
|
||||
// Clear if Illegal Operand or Zero Division exceptions are set.
|
||||
__ testl(rax, Immediate(5)); // #IO and #ZD flags of FPU status word.
|
||||
__ j(zero, &no_exceptions);
|
||||
__ fnclex();
|
||||
__ bind(&no_exceptions);
|
||||
}
|
||||
|
||||
// Use fpmod to restrict argument to the range +/-2*PI.
|
||||
__ fldpi();
|
||||
__ fadd(0);
|
||||
__ fld(1);
|
||||
// FPU Stack: input, 2*pi, input.
|
||||
{
|
||||
Label no_exceptions;
|
||||
__ fwait();
|
||||
__ fnstsw_ax();
|
||||
// Clear if Illegal Operand or Zero Division exceptions are set.
|
||||
__ testl(rax, Immediate(5)); // #IO and #ZD flags of FPU status word.
|
||||
__ j(zero, &no_exceptions);
|
||||
__ fnclex();
|
||||
__ bind(&no_exceptions);
|
||||
// Compute st(0) % st(1)
|
||||
{
|
||||
NearLabel partial_remainder_loop;
|
||||
__ bind(&partial_remainder_loop);
|
||||
__ fprem1();
|
||||
__ fwait();
|
||||
__ fnstsw_ax();
|
||||
__ testl(rax, Immediate(0x400)); // Check C2 bit of FPU status word.
|
||||
// If C2 is set, computation only has partial result. Loop to
|
||||
// continue computation.
|
||||
__ j(not_zero, &partial_remainder_loop);
|
||||
}
|
||||
|
||||
// Compute st(0) % st(1)
|
||||
{
|
||||
NearLabel partial_remainder_loop;
|
||||
__ bind(&partial_remainder_loop);
|
||||
__ fprem1();
|
||||
__ fwait();
|
||||
__ fnstsw_ax();
|
||||
__ testl(rax, Immediate(0x400)); // Check C2 bit of FPU status word.
|
||||
// If C2 is set, computation only has partial result. Loop to
|
||||
// continue computation.
|
||||
__ j(not_zero, &partial_remainder_loop);
|
||||
// FPU Stack: input, 2*pi, input % 2*pi
|
||||
__ fstp(2);
|
||||
// FPU Stack: input % 2*pi, 2*pi,
|
||||
__ fstp(0);
|
||||
// FPU Stack: input % 2*pi
|
||||
__ bind(&in_range);
|
||||
switch (type_) {
|
||||
case TranscendentalCache::SIN:
|
||||
__ fsin();
|
||||
break;
|
||||
case TranscendentalCache::COS:
|
||||
__ fcos();
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
__ bind(&done);
|
||||
} else {
|
||||
ASSERT(type_ == TranscendentalCache::LOG);
|
||||
__ fldln2();
|
||||
__ fxch();
|
||||
__ fyl2x();
|
||||
}
|
||||
// FPU Stack: input, 2*pi, input % 2*pi
|
||||
__ fstp(2);
|
||||
// FPU Stack: input % 2*pi, 2*pi,
|
||||
__ fstp(0);
|
||||
// FPU Stack: input % 2*pi
|
||||
__ bind(&in_range);
|
||||
switch (type_) {
|
||||
case TranscendentalCache::SIN:
|
||||
__ fsin();
|
||||
break;
|
||||
case TranscendentalCache::COS:
|
||||
__ fcos();
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
__ bind(&done);
|
||||
}
|
||||
|
||||
|
||||
|
@ -7111,6 +7111,15 @@ void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) {
|
||||
}
|
||||
|
||||
|
||||
void CodeGenerator::GenerateMathLog(ZoneList<Expression*>* args) {
|
||||
ASSERT_EQ(args->length(), 1);
|
||||
Load(args->at(0));
|
||||
TranscendentalCacheStub stub(TranscendentalCache::LOG);
|
||||
Result result = frame_->CallStub(&stub, 1);
|
||||
frame_->Push(&result);
|
||||
}
|
||||
|
||||
|
||||
// Generates the Math.sqrt method. Please note - this function assumes that
|
||||
// the callsite has executed ToNumber on the argument.
|
||||
void CodeGenerator::GenerateMathSqrt(ZoneList<Expression*>* args) {
|
||||
|
@ -664,14 +664,16 @@ class CodeGenerator: public AstVisitor {
|
||||
void GenerateMathSin(ZoneList<Expression*>* args);
|
||||
void GenerateMathCos(ZoneList<Expression*>* args);
|
||||
void GenerateMathSqrt(ZoneList<Expression*>* args);
|
||||
void GenerateMathLog(ZoneList<Expression*>* args);
|
||||
|
||||
// Check whether two RegExps are equivalent.
|
||||
void GenerateIsRegExpEquivalent(ZoneList<Expression*>* args);
|
||||
|
||||
void GenerateHasCachedArrayIndex(ZoneList<Expression*>* args);
|
||||
void GenerateGetCachedArrayIndex(ZoneList<Expression*>* args);
|
||||
void GenerateFastAsciiArrayJoin(ZoneList<Expression*>* args);
|
||||
|
||||
// Simple condition analysis.
|
||||
// Simple condition analysis.
|
||||
enum ConditionAnalysis {
|
||||
ALWAYS_TRUE,
|
||||
ALWAYS_FALSE,
|
||||
|
@ -906,7 +906,9 @@ int DisassemblerX64::RegisterFPUInstruction(int escape_opcode,
|
||||
case 0xE4: mnem = "ftst"; break;
|
||||
case 0xE8: mnem = "fld1"; break;
|
||||
case 0xEB: mnem = "fldpi"; break;
|
||||
case 0xED: mnem = "fldln2"; break;
|
||||
case 0xEE: mnem = "fldz"; break;
|
||||
case 0xF1: mnem = "fyl2x"; break;
|
||||
case 0xF5: mnem = "fprem1"; break;
|
||||
case 0xF7: mnem = "fincstp"; break;
|
||||
case 0xF8: mnem = "fprem"; break;
|
||||
|
@ -2623,6 +2623,16 @@ void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) {
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) {
|
||||
// Load the argument on the stack and call the stub.
|
||||
TranscendentalCacheStub stub(TranscendentalCache::LOG);
|
||||
ASSERT(args->length() == 1);
|
||||
VisitForStackValue(args->at(0));
|
||||
__ CallStub(&stub);
|
||||
context()->Plug(rax);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) {
|
||||
// Load the argument on the stack and call the runtime function.
|
||||
ASSERT(args->length() == 1);
|
||||
|
Loading…
Reference in New Issue
Block a user