Commit 5656d64e authored by whesse@chromium.org's avatar whesse@chromium.org

Add untagged double versions of Math.sin and Math.cos. Merge classes...

Add untagged double versions of Math.sin and Math.cos.  Merge classes TranscendentalCacheStub and TranscendentalCacheSSE2Stub.
Review URL: http://codereview.chromium.org/5996002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6083 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 7cc61e69
...@@ -1375,6 +1375,12 @@ LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) { ...@@ -1375,6 +1375,12 @@ LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
case kMathLog: case kMathLog:
Abort("MathLog LUnaryMathOperation not implemented"); Abort("MathLog LUnaryMathOperation not implemented");
return NULL; return NULL;
case kMathCos:
Abort("MathCos LUnaryMathOperation not implemented");
return NULL;
case kMathSin:
Abort("MathSin LUnaryMathOperation not implemented");
return NULL;
default: default:
UNREACHABLE(); UNREACHABLE();
return NULL; return NULL;
......
...@@ -1547,7 +1547,7 @@ void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { ...@@ -1547,7 +1547,7 @@ void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) {
void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) {
Abort("LUnaryMathOperation unimplemented."); Abort("DoMathAbs unimplemented.");
} }
...@@ -1562,9 +1562,6 @@ void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { ...@@ -1562,9 +1562,6 @@ void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) {
void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) { void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) {
ASSERT(instr->op() == kMathFloor ||
instr->op() == kMathAbs);
switch (instr->op()) { switch (instr->op()) {
case kMathAbs: case kMathAbs:
DoMathAbs(instr); DoMathAbs(instr);
...@@ -1576,6 +1573,7 @@ void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) { ...@@ -1576,6 +1573,7 @@ void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) {
DoMathSqrt(instr); DoMathSqrt(instr);
break; break;
default: default:
Abort("Unimplemented type of LUnaryMathOperation.");
UNREACHABLE(); UNREACHABLE();
} }
} }
......
...@@ -1968,6 +1968,8 @@ class GCTracer BASE_EMBEDDED { ...@@ -1968,6 +1968,8 @@ class GCTracer BASE_EMBEDDED {
class TranscendentalCache { class TranscendentalCache {
public: public:
enum Type {ACOS, ASIN, ATAN, COS, EXP, LOG, SIN, TAN, kNumberOfCaches}; enum Type {ACOS, ASIN, ATAN, COS, EXP, LOG, SIN, TAN, kNumberOfCaches};
static const int kTranscendentalTypeBits = 3;
STATIC_ASSERT((1 << kTranscendentalTypeBits) >= kNumberOfCaches);
explicit TranscendentalCache(Type t); explicit TranscendentalCache(Type t);
......
...@@ -1389,6 +1389,8 @@ class HUnaryMathOperation: public HUnaryOperation { ...@@ -1389,6 +1389,8 @@ class HUnaryMathOperation: public HUnaryOperation {
case kMathSqrt: case kMathSqrt:
case kMathPowHalf: case kMathPowHalf:
case kMathLog: case kMathLog:
case kMathSin:
case kMathCos:
set_representation(Representation::Double()); set_representation(Representation::Double());
break; break;
default: default:
...@@ -1411,6 +1413,8 @@ class HUnaryMathOperation: public HUnaryOperation { ...@@ -1411,6 +1413,8 @@ class HUnaryMathOperation: public HUnaryOperation {
case kMathSqrt: case kMathSqrt:
case kMathPowHalf: case kMathPowHalf:
case kMathLog: case kMathLog:
case kMathSin:
case kMathCos:
return Representation::Double(); return Representation::Double();
break; break;
case kMathAbs: case kMathAbs:
......
...@@ -4097,6 +4097,8 @@ bool HGraphBuilder::TryMathFunctionInline(Call* expr) { ...@@ -4097,6 +4097,8 @@ bool HGraphBuilder::TryMathFunctionInline(Call* expr) {
case kMathAbs: case kMathAbs:
case kMathSqrt: case kMathSqrt:
case kMathLog: case kMathLog:
case kMathSin:
case kMathCos:
if (argument_count == 2) { if (argument_count == 2) {
HValue* argument = Pop(); HValue* argument = Pop();
Drop(1); // Receiver. Drop(1); // Receiver.
......
...@@ -2472,12 +2472,26 @@ void TypeRecordingBinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) { ...@@ -2472,12 +2472,26 @@ void TypeRecordingBinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
void TranscendentalCacheStub::Generate(MacroAssembler* masm) { void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
// Input on stack: // TAGGED case:
// esp[4]: argument (should be number). // Input:
// esp[4]: tagged number input argument (should be number).
// esp[0]: return address. // esp[0]: return address.
// Test that eax is a number. // Output:
// eax: tagged double result.
// UNTAGGED case:
// Input::
// esp[0]: return address.
// xmm1: untagged double input argument
// Output:
// xmm1: untagged double result.
Label runtime_call; Label runtime_call;
Label runtime_call_clear_stack; Label runtime_call_clear_stack;
Label skip_cache;
Label call_runtime;
const bool tagged = (argument_type_ == TAGGED);
if (tagged) {
// Test that eax is a number.
NearLabel input_not_smi; NearLabel input_not_smi;
NearLabel loaded; NearLabel loaded;
__ mov(eax, Operand(esp, kPointerSize)); __ mov(eax, Operand(esp, kPointerSize));
...@@ -2506,7 +2520,18 @@ void TranscendentalCacheStub::Generate(MacroAssembler* masm) { ...@@ -2506,7 +2520,18 @@ void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
__ mov(ebx, FieldOperand(eax, HeapNumber::kMantissaOffset)); __ mov(ebx, FieldOperand(eax, HeapNumber::kMantissaOffset));
__ bind(&loaded); __ bind(&loaded);
// ST[0] == double value } else { // UNTAGGED.
if (CpuFeatures::IsSupported(SSE4_1)) {
CpuFeatures::Scope sse4_scope(SSE4_1);
__ pextrd(Operand(edx), xmm1, 0x1); // copy xmm1[63..32] to edx.
} else {
__ pshufd(xmm0, xmm1, 0x1);
__ movd(Operand(edx), xmm0);
}
__ movd(Operand(ebx), xmm1);
}
// ST[0] or xmm1 == double value
// ebx = low 32 bits of double value // ebx = low 32 bits of double value
// edx = high 32 bits of double value // edx = high 32 bits of double value
// Compute hash (the shifts are arithmetic): // Compute hash (the shifts are arithmetic):
...@@ -2522,7 +2547,7 @@ void TranscendentalCacheStub::Generate(MacroAssembler* masm) { ...@@ -2522,7 +2547,7 @@ void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
ASSERT(IsPowerOf2(TranscendentalCache::kCacheSize)); ASSERT(IsPowerOf2(TranscendentalCache::kCacheSize));
__ and_(Operand(ecx), Immediate(TranscendentalCache::kCacheSize - 1)); __ and_(Operand(ecx), Immediate(TranscendentalCache::kCacheSize - 1));
// ST[0] == double value. // ST[0] or xmm1 == double value.
// ebx = low 32 bits of double value. // ebx = low 32 bits of double value.
// edx = high 32 bits of double value. // edx = high 32 bits of double value.
// ecx = TranscendentalCache::hash(double value). // ecx = TranscendentalCache::hash(double value).
...@@ -2559,31 +2584,72 @@ void TranscendentalCacheStub::Generate(MacroAssembler* masm) { ...@@ -2559,31 +2584,72 @@ void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
__ j(not_equal, &cache_miss); __ j(not_equal, &cache_miss);
// Cache hit! // Cache hit!
__ mov(eax, Operand(ecx, 2 * kIntSize)); __ mov(eax, Operand(ecx, 2 * kIntSize));
if (tagged) {
__ fstp(0); __ fstp(0);
__ ret(kPointerSize); __ ret(kPointerSize);
} else { // UNTAGGED.
__ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
__ Ret();
}
__ bind(&cache_miss); __ bind(&cache_miss);
// Update cache with new value. // Update cache with new value.
// We are short on registers, so use no_reg as scratch. // We are short on registers, so use no_reg as scratch.
// This gives slightly larger code. // This gives slightly larger code.
if (tagged) {
__ AllocateHeapNumber(eax, edi, no_reg, &runtime_call_clear_stack); __ AllocateHeapNumber(eax, edi, no_reg, &runtime_call_clear_stack);
} else { // UNTAGGED.
__ AllocateHeapNumber(eax, edi, no_reg, &skip_cache);
__ sub(Operand(esp), Immediate(kDoubleSize));
__ movdbl(Operand(esp, 0), xmm1);
__ fld_d(Operand(esp, 0));
__ add(Operand(esp), Immediate(kDoubleSize));
}
GenerateOperation(masm); GenerateOperation(masm);
__ mov(Operand(ecx, 0), ebx); __ mov(Operand(ecx, 0), ebx);
__ mov(Operand(ecx, kIntSize), edx); __ mov(Operand(ecx, kIntSize), edx);
__ mov(Operand(ecx, 2 * kIntSize), eax); __ mov(Operand(ecx, 2 * kIntSize), eax);
__ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
if (tagged) {
__ ret(kPointerSize); __ ret(kPointerSize);
} else { // UNTAGGED.
__ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
__ Ret();
// Skip cache and return answer directly, only in untagged case.
__ bind(&skip_cache);
__ sub(Operand(esp), Immediate(kDoubleSize));
__ movdbl(Operand(esp, 0), xmm1);
__ fld_d(Operand(esp, 0));
GenerateOperation(masm);
__ fstp_d(Operand(esp, 0));
__ movdbl(xmm1, Operand(esp, 0));
__ add(Operand(esp), Immediate(kDoubleSize));
__ Ret();
}
// Call runtime, doing whatever allocation and cleanup is necessary.
if (tagged) {
__ bind(&runtime_call_clear_stack); __ bind(&runtime_call_clear_stack);
__ fstp(0); __ fstp(0);
__ bind(&runtime_call); __ bind(&runtime_call);
__ TailCallExternalReference(ExternalReference(RuntimeFunction()), 1, 1); __ TailCallExternalReference(ExternalReference(RuntimeFunction()), 1, 1);
} else { // UNTAGGED.
__ bind(&call_runtime);
__ AllocateHeapNumber(eax, edi, no_reg, &skip_cache);
__ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm1);
__ EnterInternalFrame();
__ push(eax);
__ CallRuntime(RuntimeFunction(), 1);
__ LeaveInternalFrame();
__ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
__ Ret();
}
} }
Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() { Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() {
switch (type_) { switch (type_) {
// 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; case TranscendentalCache::LOG: return Runtime::kMath_log;
...@@ -2596,14 +2662,14 @@ Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() { ...@@ -2596,14 +2662,14 @@ 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 // Input value is on FP stack, and also in ebx/edx.
// (a newly allocated HeapNumber) is in eax. // Input value is possibly in xmm1.
NearLabel done; // Address of result (a newly allocated HeapNumber) may be in eax.
if (type_ == TranscendentalCache::SIN || type_ == TranscendentalCache::COS) { if (type_ == TranscendentalCache::SIN || type_ == TranscendentalCache::COS) {
// Both fsin and fcos require arguments in the range +/-2^63 and // Both fsin and fcos require arguments in the range +/-2^63 and
// return NaN for infinities and NaN. They can share all code except // return NaN for infinities and NaN. They can share all code except
// the actual fsin/fcos operation. // the actual fsin/fcos operation.
NearLabel in_range; NearLabel in_range, done;
// If argument is outside the range -2^63..2^63, fsin/cos doesn't // If argument is outside the range -2^63..2^63, fsin/cos doesn't
// work. We must reduce it to the appropriate range. // work. We must reduce it to the appropriate range.
__ mov(edi, edx); __ mov(edi, edx);
...@@ -2683,145 +2749,6 @@ void TranscendentalCacheStub::GenerateOperation(MacroAssembler* masm) { ...@@ -2683,145 +2749,6 @@ void TranscendentalCacheStub::GenerateOperation(MacroAssembler* masm) {
} }
void TranscendentalCacheSSE2Stub::Generate(MacroAssembler* masm) {
// Input on stack:
// esp[0]: return address.
// Input in registers:
// xmm1: untagged double input argument.
// Output:
// xmm1: untagged double result.
Label skip_cache;
Label call_runtime;
// Input is an untagged double in xmm1.
// Compute hash (the shifts are arithmetic):
// h = (low ^ high); h ^= h >> 16; h ^= h >> 8; h = h & (cacheSize - 1);
if (CpuFeatures::IsSupported(SSE4_1)) {
CpuFeatures::Scope sse4_scope(SSE4_1);
__ pextrd(Operand(edx), xmm1, 0x1); // copy xmm1[63..32] to edx.
} else {
__ pshufd(xmm0, xmm1, 0x1);
__ movd(Operand(edx), xmm0);
}
__ movd(Operand(ebx), xmm1);
// xmm1 = double value
// ebx = low 32 bits of double value
// edx = high 32 bits of double value
// Compute hash (the shifts are arithmetic):
// h = (low ^ high); h ^= h >> 16; h ^= h >> 8; h = h & (cacheSize - 1);
__ mov(ecx, ebx);
__ xor_(ecx, Operand(edx));
__ mov(eax, ecx);
__ sar(eax, 16);
__ xor_(ecx, Operand(eax));
__ mov(eax, ecx);
__ sar(eax, 8);
__ xor_(ecx, Operand(eax));
ASSERT(IsPowerOf2(TranscendentalCache::kCacheSize));
__ and_(Operand(ecx), Immediate(TranscendentalCache::kCacheSize - 1));
// xmm1 = double value.
// ebx = low 32 bits of double value.
// edx = high 32 bits of double value.
// ecx = TranscendentalCache::hash(double value).
__ mov(eax,
Immediate(ExternalReference::transcendental_cache_array_address()));
// Eax points to cache array.
__ mov(eax, Operand(eax, type_ * sizeof(TranscendentalCache::caches_[0])));
// Eax points to the cache for the type type_.
// If NULL, the cache hasn't been initialized yet, so go through runtime.
__ test(eax, Operand(eax));
__ j(zero, &call_runtime);
#ifdef DEBUG
// Check that the layout of cache elements match expectations.
{ TranscendentalCache::Element test_elem[2];
char* elem_start = reinterpret_cast<char*>(&test_elem[0]);
char* elem2_start = reinterpret_cast<char*>(&test_elem[1]);
char* elem_in0 = reinterpret_cast<char*>(&(test_elem[0].in[0]));
char* elem_in1 = reinterpret_cast<char*>(&(test_elem[0].in[1]));
char* elem_out = reinterpret_cast<char*>(&(test_elem[0].output));
CHECK_EQ(12, elem2_start - elem_start); // Two uint_32's and a pointer.
CHECK_EQ(0, elem_in0 - elem_start);
CHECK_EQ(kIntSize, elem_in1 - elem_start);
CHECK_EQ(2 * kIntSize, elem_out - elem_start);
}
#endif
// Find the address of the ecx'th entry in the cache, i.e., &eax[ecx*12].
__ lea(ecx, Operand(ecx, ecx, times_2, 0));
__ lea(ecx, Operand(eax, ecx, times_4, 0));
// Check if cache matches: Double value is stored in uint32_t[2] array.
NearLabel cache_miss;
__ cmp(ebx, Operand(ecx, 0));
__ j(not_equal, &cache_miss);
__ cmp(edx, Operand(ecx, kIntSize));
__ j(not_equal, &cache_miss);
// Cache hit!
__ mov(eax, Operand(ecx, 2 * kIntSize));
__ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
__ Ret();
__ bind(&cache_miss);
// Update cache with new value.
// We are short on registers, so use no_reg as scratch.
// This gives slightly larger code.
__ AllocateHeapNumber(eax, edi, no_reg, &skip_cache);
__ sub(Operand(esp), Immediate(kDoubleSize));
__ movdbl(Operand(esp, 0), xmm1);
__ fld_d(Operand(esp, 0));
__ add(Operand(esp), Immediate(kDoubleSize));
GenerateOperation(masm);
__ mov(Operand(ecx, 0), ebx);
__ mov(Operand(ecx, kIntSize), edx);
__ mov(Operand(ecx, 2 * kIntSize), eax);
__ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
__ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
__ Ret();
__ bind(&skip_cache);
__ sub(Operand(esp), Immediate(kDoubleSize));
__ movdbl(Operand(esp, 0), xmm1);
__ fld_d(Operand(esp, 0));
GenerateOperation(masm);
__ fstp_d(Operand(esp, 0));
__ movdbl(xmm1, Operand(esp, 0));
__ add(Operand(esp), Immediate(kDoubleSize));
__ Ret();
__ bind(&call_runtime);
__ AllocateHeapNumber(eax, edi, no_reg, &skip_cache);
__ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm1);
__ EnterInternalFrame();
__ push(eax);
__ CallRuntime(RuntimeFunction(), 1);
__ LeaveInternalFrame();
__ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
__ Ret();
}
Runtime::FunctionId TranscendentalCacheSSE2Stub::RuntimeFunction() {
switch (type_) {
// Add more cases when necessary.
case TranscendentalCache::LOG: return Runtime::kMath_log;
default:
UNIMPLEMENTED();
return Runtime::kAbort;
}
}
void TranscendentalCacheSSE2Stub::GenerateOperation(MacroAssembler* masm) {
// Only free register is edi.
// Input value is on FP stack and in xmm1.
ASSERT(type_ == TranscendentalCache::LOG);
__ fldln2();
__ fxch();
__ fyl2x();
}
// Get the integer part of a heap number. Surprisingly, all this bit twiddling // Get the integer part of a heap number. Surprisingly, all this bit twiddling
// is faster than using the built-in instructions on floating point registers. // is faster than using the built-in instructions on floating point registers.
// Trashes edi and ebx. Dest is ecx. Source cannot be ecx or one of the // Trashes edi and ebx. Dest is ecx. Source cannot be ecx or one of the
......
...@@ -40,32 +40,21 @@ namespace internal { ...@@ -40,32 +40,21 @@ namespace internal {
// TranscendentalCache runtime function. // TranscendentalCache runtime function.
class TranscendentalCacheStub: public CodeStub { class TranscendentalCacheStub: public CodeStub {
public: public:
explicit TranscendentalCacheStub(TranscendentalCache::Type type) enum ArgumentType {
: type_(type) {} TAGGED = 0,
void Generate(MacroAssembler* masm); UNTAGGED = 1 << TranscendentalCache::kTranscendentalTypeBits
private: };
TranscendentalCache::Type type_;
Major MajorKey() { return TranscendentalCache; }
int MinorKey() { return type_; }
Runtime::FunctionId RuntimeFunction();
void GenerateOperation(MacroAssembler* masm);
};
// Check the transcendental cache, or generate the result, using SSE2. explicit TranscendentalCacheStub(TranscendentalCache::Type type,
// The argument and result will be in xmm1. ArgumentType argument_type)
// Only supports TranscendentalCache::LOG at this point. : type_(type), argument_type_(argument_type) {}
class TranscendentalCacheSSE2Stub: public CodeStub {
public:
explicit TranscendentalCacheSSE2Stub(TranscendentalCache::Type type)
: type_(type) {}
void Generate(MacroAssembler* masm); void Generate(MacroAssembler* masm);
private: private:
TranscendentalCache::Type type_; TranscendentalCache::Type type_;
ArgumentType argument_type_;
Major MajorKey() { return TranscendentalCacheSSE2; } Major MajorKey() { return TranscendentalCache; }
int MinorKey() { return type_; } int MinorKey() { return type_ | argument_type_; }
Runtime::FunctionId RuntimeFunction(); Runtime::FunctionId RuntimeFunction();
void GenerateOperation(MacroAssembler* masm); void GenerateOperation(MacroAssembler* masm);
}; };
......
...@@ -7912,7 +7912,8 @@ void CodeGenerator::GenerateMathPow(ZoneList<Expression*>* args) { ...@@ -7912,7 +7912,8 @@ void CodeGenerator::GenerateMathPow(ZoneList<Expression*>* args) {
void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) { void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) {
ASSERT_EQ(args->length(), 1); ASSERT_EQ(args->length(), 1);
Load(args->at(0)); Load(args->at(0));
TranscendentalCacheStub stub(TranscendentalCache::SIN); TranscendentalCacheStub stub(TranscendentalCache::SIN,
TranscendentalCacheStub::TAGGED);
Result result = frame_->CallStub(&stub, 1); Result result = frame_->CallStub(&stub, 1);
frame_->Push(&result); frame_->Push(&result);
} }
...@@ -7921,7 +7922,8 @@ void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) { ...@@ -7921,7 +7922,8 @@ void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) {
void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) { void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) {
ASSERT_EQ(args->length(), 1); ASSERT_EQ(args->length(), 1);
Load(args->at(0)); Load(args->at(0));
TranscendentalCacheStub stub(TranscendentalCache::COS); TranscendentalCacheStub stub(TranscendentalCache::COS,
TranscendentalCacheStub::TAGGED);
Result result = frame_->CallStub(&stub, 1); Result result = frame_->CallStub(&stub, 1);
frame_->Push(&result); frame_->Push(&result);
} }
...@@ -7930,7 +7932,8 @@ void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) { ...@@ -7930,7 +7932,8 @@ void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) {
void CodeGenerator::GenerateMathLog(ZoneList<Expression*>* args) { void CodeGenerator::GenerateMathLog(ZoneList<Expression*>* args) {
ASSERT_EQ(args->length(), 1); ASSERT_EQ(args->length(), 1);
Load(args->at(0)); Load(args->at(0));
TranscendentalCacheStub stub(TranscendentalCache::LOG); TranscendentalCacheStub stub(TranscendentalCache::LOG,
TranscendentalCacheStub::TAGGED);
Result result = frame_->CallStub(&stub, 1); Result result = frame_->CallStub(&stub, 1);
frame_->Push(&result); frame_->Push(&result);
} }
......
...@@ -3067,7 +3067,8 @@ void FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) { ...@@ -3067,7 +3067,8 @@ void FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) {
void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) {
// Load the argument on the stack and call the stub. // Load the argument on the stack and call the stub.
TranscendentalCacheStub stub(TranscendentalCache::SIN); TranscendentalCacheStub stub(TranscendentalCache::SIN,
TranscendentalCacheStub::TAGGED);
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
__ CallStub(&stub); __ CallStub(&stub);
...@@ -3077,7 +3078,8 @@ void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) { ...@@ -3077,7 +3078,8 @@ void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) {
void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) {
// Load the argument on the stack and call the stub. // Load the argument on the stack and call the stub.
TranscendentalCacheStub stub(TranscendentalCache::COS); TranscendentalCacheStub stub(TranscendentalCache::COS,
TranscendentalCacheStub::TAGGED);
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
__ CallStub(&stub); __ CallStub(&stub);
...@@ -3087,7 +3089,8 @@ void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) { ...@@ -3087,7 +3089,8 @@ void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) {
void FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) {
// Load the argument on the stack and call the stub. // Load the argument on the stack and call the stub.
TranscendentalCacheStub stub(TranscendentalCache::LOG); TranscendentalCacheStub stub(TranscendentalCache::LOG,
TranscendentalCacheStub::TAGGED);
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
__ CallStub(&stub); __ CallStub(&stub);
......
...@@ -686,7 +686,8 @@ void LCodeGen::DoCallStub(LCallStub* instr) { ...@@ -686,7 +686,8 @@ void LCodeGen::DoCallStub(LCallStub* instr) {
break; break;
} }
case CodeStub::TranscendentalCache: { case CodeStub::TranscendentalCache: {
TranscendentalCacheStub stub(instr->transcendental_type()); TranscendentalCacheStub stub(instr->transcendental_type(),
TranscendentalCacheStub::TAGGED);
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
break; break;
} }
...@@ -2314,7 +2315,24 @@ void LCodeGen::DoPower(LPower* instr) { ...@@ -2314,7 +2315,24 @@ void LCodeGen::DoPower(LPower* instr) {
void LCodeGen::DoMathLog(LUnaryMathOperation* instr) { void LCodeGen::DoMathLog(LUnaryMathOperation* instr) {
ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
TranscendentalCacheSSE2Stub stub(TranscendentalCache::LOG); TranscendentalCacheStub stub(TranscendentalCache::LOG,
TranscendentalCacheStub::UNTAGGED);
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
}
void LCodeGen::DoMathCos(LUnaryMathOperation* instr) {
ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
TranscendentalCacheStub stub(TranscendentalCache::COS,
TranscendentalCacheStub::UNTAGGED);
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
}
void LCodeGen::DoMathSin(LUnaryMathOperation* instr) {
ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
TranscendentalCacheStub stub(TranscendentalCache::SIN,
TranscendentalCacheStub::UNTAGGED);
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
} }
...@@ -2336,6 +2354,12 @@ void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) { ...@@ -2336,6 +2354,12 @@ void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) {
case kMathPowHalf: case kMathPowHalf:
DoMathPowHalf(instr); DoMathPowHalf(instr);
break; break;
case kMathCos:
DoMathCos(instr);
break;
case kMathSin:
DoMathSin(instr);
break;
case kMathLog: case kMathLog:
DoMathLog(instr); DoMathLog(instr);
break; break;
......
...@@ -177,6 +177,8 @@ class LCodeGen BASE_EMBEDDED { ...@@ -177,6 +177,8 @@ class LCodeGen BASE_EMBEDDED {
void DoMathSqrt(LUnaryMathOperation* instr); void DoMathSqrt(LUnaryMathOperation* instr);
void DoMathPowHalf(LUnaryMathOperation* instr); void DoMathPowHalf(LUnaryMathOperation* instr);
void DoMathLog(LUnaryMathOperation* instr); void DoMathLog(LUnaryMathOperation* instr);
void DoMathCos(LUnaryMathOperation* instr);
void DoMathSin(LUnaryMathOperation* instr);
// Support for recording safepoint and position information. // Support for recording safepoint and position information.
void RecordSafepoint(LPointerMap* pointers, int deoptimization_index); void RecordSafepoint(LPointerMap* pointers, int deoptimization_index);
......
...@@ -1361,7 +1361,7 @@ LInstruction* LChunkBuilder::DoCallConstantFunction( ...@@ -1361,7 +1361,7 @@ LInstruction* LChunkBuilder::DoCallConstantFunction(
LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) { LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
BuiltinFunctionId op = instr->op(); BuiltinFunctionId op = instr->op();
if (op == kMathLog) { if (op == kMathLog || op == kMathSin || op == kMathCos) {
LOperand* input = UseFixedDouble(instr->value(), xmm1); LOperand* input = UseFixedDouble(instr->value(), xmm1);
LInstruction* result = new LUnaryMathOperation(input); LInstruction* result = new LUnaryMathOperation(input);
return MarkAsCall(DefineFixedDouble(result, xmm1), instr); return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
......
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