Commit 66836efb authored by whesse@chromium.org's avatar whesse@chromium.org

Add generated code to calculate Math.log and to search Transcendental cache...

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