From 3135110af811869975dc5bfcfe4f94b70b78927e Mon Sep 17 00:00:00 2001 From: "lrn@chromium.org" Date: Tue, 23 Feb 2010 10:29:02 +0000 Subject: [PATCH] IA32: Native access to TranscendentalCache for sin/cos. Review URL: http://codereview.chromium.org/652041 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3929 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/codegen-arm.cc | 18 +++ src/arm/codegen-arm.h | 4 + src/assembler.cc | 5 + src/assembler.h | 1 + src/code-stubs.h | 1 + src/codegen.cc | 2 + src/heap.h | 13 +++ src/ia32/assembler-ia32.cc | 23 ++++ src/ia32/assembler-ia32.h | 4 + src/ia32/codegen-ia32.cc | 224 +++++++++++++++++++++++++++++++++++++ src/ia32/codegen-ia32.h | 20 ++++ src/ia32/disasm-ia32.cc | 2 + src/math.js | 4 +- src/runtime.cc | 15 +++ src/serialize.cc | 4 + src/v8-counters.h | 19 +++- src/x64/codegen-x64.cc | 18 +++ src/x64/codegen-x64.h | 6 +- 18 files changed, 379 insertions(+), 4 deletions(-) diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc index 95c50f262..e47d39210 100644 --- a/src/arm/codegen-arm.cc +++ b/src/arm/codegen-arm.cc @@ -3628,6 +3628,24 @@ void CodeGenerator::GenerateNumberToString(ZoneList* args) { } +void CodeGenerator::GenerateMathSin(ZoneList* args) { + ASSERT_EQ(args->length(), 1); + // Load the argument on the stack and jump to the runtime. + Load(args->at(0)); + frame_->CallRuntime(Runtime::kMath_sin, 1); + frame_->EmitPush(r0); +} + + +void CodeGenerator::GenerateMathCos(ZoneList* args) { + ASSERT_EQ(args->length(), 1); + // Load the argument on the stack and jump to the runtime. + Load(args->at(0)); + frame_->CallRuntime(Runtime::kMath_cos, 1); + frame_->EmitPush(r0); +} + + void CodeGenerator::GenerateObjectEquals(ZoneList* args) { VirtualFrame::SpilledScope spilled_scope; ASSERT(args->length() == 2); diff --git a/src/arm/codegen-arm.h b/src/arm/codegen-arm.h index 1a2e5525a..22dd854a2 100644 --- a/src/arm/codegen-arm.h +++ b/src/arm/codegen-arm.h @@ -393,6 +393,10 @@ class CodeGenerator: public AstVisitor { // Fast support for number to string. void GenerateNumberToString(ZoneList* args); + // Fast call to sine function. + void GenerateMathSin(ZoneList* args); + void GenerateMathCos(ZoneList* args); + // Simple condition analysis. enum ConditionAnalysis { ALWAYS_TRUE, diff --git a/src/assembler.cc b/src/assembler.cc index 96d516f18..8959b90a3 100644 --- a/src/assembler.cc +++ b/src/assembler.cc @@ -579,6 +579,11 @@ ExternalReference ExternalReference::random_positive_smi_function() { } +ExternalReference ExternalReference::transcendental_cache_array_address() { + return ExternalReference(TranscendentalCache::cache_array_address()); +} + + ExternalReference ExternalReference::keyed_lookup_cache_keys() { return ExternalReference(KeyedLookupCache::keys_address()); } diff --git a/src/assembler.h b/src/assembler.h index f4013061e..30be00237 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -400,6 +400,7 @@ class ExternalReference BASE_EMBEDDED { static ExternalReference perform_gc_function(); static ExternalReference random_positive_smi_function(); + static ExternalReference transcendental_cache_array_address(); // Static data in the keyed lookup cache. static ExternalReference keyed_lookup_cache_keys(); diff --git a/src/code-stubs.h b/src/code-stubs.h index 3901a6478..d5189c272 100644 --- a/src/code-stubs.h +++ b/src/code-stubs.h @@ -48,6 +48,7 @@ namespace internal { V(FastNewClosure) \ V(FastNewContext) \ V(FastCloneShallowArray) \ + V(TranscendentalCache) \ V(GenericUnaryOp) \ V(RevertToNumber) \ V(ToBoolean) \ diff --git a/src/codegen.cc b/src/codegen.cc index dbd1100d9..bc722bbeb 100644 --- a/src/codegen.cc +++ b/src/codegen.cc @@ -379,6 +379,8 @@ CodeGenerator::InlineRuntimeLUT CodeGenerator::kInlineRuntimeLUT[] = { {&CodeGenerator::GenerateStringCompare, "_StringCompare"}, {&CodeGenerator::GenerateRegExpExec, "_RegExpExec"}, {&CodeGenerator::GenerateNumberToString, "_NumberToString"}, + {&CodeGenerator::GenerateMathSin, "_Math_sin"}, + {&CodeGenerator::GenerateMathCos, "_Math_cos"}, }; diff --git a/src/heap.h b/src/heap.h index 3f34df72b..9948b96d7 100644 --- a/src/heap.h +++ b/src/heap.h @@ -1610,6 +1610,7 @@ class TranscendentalCache { if (e.in[0] == c.integers[0] && e.in[1] == c.integers[1]) { ASSERT(e.output != NULL); + Counters::transcendental_cache_hit.Increment(); return e.output; } double answer = Calculate(input); @@ -1619,6 +1620,7 @@ class TranscendentalCache { elements_[hash].in[1] = c.integers[1]; elements_[hash].output = heap_number; } + Counters::transcendental_cache_miss.Increment(); return heap_number; } @@ -1659,6 +1661,17 @@ class TranscendentalCache { hash ^= hash >> 8; return (hash & (kCacheSize - 1)); } + + static Address cache_array_address() { + // Used to create an external reference. + return reinterpret_cast
(caches_); + } + + // Allow access to the caches_ array as an ExternalReference. + friend class ExternalReference; + // Inline implementation of the caching. + friend class TranscendentalCacheStub; + static TranscendentalCache* caches_[kNumberOfCaches]; Element elements_[kCacheSize]; Type type_; diff --git a/src/ia32/assembler-ia32.cc b/src/ia32/assembler-ia32.cc index ffcefe0b5..89708aae5 100644 --- a/src/ia32/assembler-ia32.cc +++ b/src/ia32/assembler-ia32.cc @@ -1637,6 +1637,13 @@ void Assembler::fld(int i) { } +void Assembler::fstp(int i) { + EnsureSpace ensure_space(this); + last_pc_ = pc_; + emit_farith(0xDD, 0xD8, i); +} + + void Assembler::fld1() { EnsureSpace ensure_space(this); last_pc_ = pc_; @@ -1645,6 +1652,14 @@ void Assembler::fld1() { } +void Assembler::fldpi() { + EnsureSpace ensure_space(this); + last_pc_ = pc_; + EMIT(0xD9); + EMIT(0xEB); +} + + void Assembler::fldz() { EnsureSpace ensure_space(this); last_pc_ = pc_; @@ -1685,6 +1700,14 @@ void Assembler::fstp_d(const Operand& adr) { } +void Assembler::fst_d(const Operand& adr) { + EnsureSpace ensure_space(this); + last_pc_ = pc_; + EMIT(0xDD); + emit_operand(edx, adr); +} + + void Assembler::fild_s(const Operand& adr) { EnsureSpace ensure_space(this); last_pc_ = pc_; diff --git a/src/ia32/assembler-ia32.h b/src/ia32/assembler-ia32.h index 3d7af82ad..36aad5e53 100644 --- a/src/ia32/assembler-ia32.h +++ b/src/ia32/assembler-ia32.h @@ -668,6 +668,7 @@ class Assembler : public Malloced { void call(Label* L); void call(byte* entry, RelocInfo::Mode rmode); void call(const Operand& adr); + void call(const ExternalReference& target); void call(Handle code, RelocInfo::Mode rmode); // Jumps @@ -683,15 +684,18 @@ class Assembler : public Malloced { // Floating-point operations void fld(int i); + void fstp(int i); void fld1(); void fldz(); + void fldpi(); void fld_s(const Operand& adr); void fld_d(const Operand& adr); void fstp_s(const Operand& adr); void fstp_d(const Operand& adr); + void fst_d(const Operand& adr); void fild_s(const Operand& adr); void fild_d(const Operand& adr); diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc index 85d8ed9bc..ecb4c497a 100644 --- a/src/ia32/codegen-ia32.cc +++ b/src/ia32/codegen-ia32.cc @@ -5825,6 +5825,24 @@ void CodeGenerator::GenerateNumberToString(ZoneList* args) { } +void CodeGenerator::GenerateMathSin(ZoneList* args) { + ASSERT_EQ(args->length(), 1); + Load(args->at(0)); + TranscendentalCacheStub stub(TranscendentalCache::SIN); + Result result = frame_->CallStub(&stub, 1); + frame_->Push(&result); +} + + +void CodeGenerator::GenerateMathCos(ZoneList* args) { + ASSERT_EQ(args->length(), 1); + Load(args->at(0)); + TranscendentalCacheStub stub(TranscendentalCache::COS); + Result result = frame_->CallStub(&stub, 1); + frame_->Push(&result); +} + + void CodeGenerator::VisitCallRuntime(CallRuntime* node) { if (CheckForInlineRuntimeCall(node)) { return; @@ -8123,6 +8141,212 @@ void GenericBinaryOpStub::GenerateReturn(MacroAssembler* masm) { } +void TranscendentalCacheStub::Generate(MacroAssembler* masm) { + // Input on stack: + // esp[4]: argument (should be number). + // esp[0]: return address. + // Test that eax is a number. + Label runtime_call; + Label runtime_call_clear_stack; + Label input_not_smi; + Label loaded; + __ mov(eax, Operand(esp, kPointerSize)); + __ test(eax, Immediate(kSmiTagMask)); + __ j(not_zero, &input_not_smi); + // Input is a smi. Untag and load it onto the FPU stack. + // Then load the low and high words of the double into ebx, edx. + ASSERT_EQ(1, kSmiTagSize); + __ sar(eax, 1); + __ sub(Operand(esp), Immediate(2 * kPointerSize)); + __ mov(Operand(esp, 0), eax); + __ fild_s(Operand(esp, 0)); + __ fst_d(Operand(esp, 0)); + __ pop(edx); + __ pop(ebx); + __ jmp(&loaded); + __ bind(&input_not_smi); + // Check if input is a HeapNumber. + __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); + __ cmp(Operand(ebx), Immediate(Factory::heap_number_map())); + __ j(not_equal, &runtime_call); + // Input is a HeapNumber. Push it on the FPU stack and load its + // low and high words into ebx, edx. + __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); + __ mov(edx, FieldOperand(eax, HeapNumber::kExponentOffset)); + __ mov(ebx, FieldOperand(eax, HeapNumber::kMantissaOffset)); + + __ bind(&loaded); + // ST[0] == double value + // ebx = low 32 bits of double value + // edx = high 32 bits of double value + // Compute hash: + // 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)); + // ST[0] == 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, &runtime_call_clear_stack); +#ifdef DEBUG + // Check that the layout of cache elements match expectations. + { // NOLINT - doesn't like a single brace on a line. + TranscendentalCache::Element test_elem[2]; + char* elem_start = reinterpret_cast(&test_elem[0]); + char* elem2_start = reinterpret_cast(&test_elem[1]); + char* elem_in0 = reinterpret_cast(&(test_elem[0].in[0])); + char* elem_in1 = reinterpret_cast(&(test_elem[0].in[1])); + char* elem_out = reinterpret_cast(&(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. + Label 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)); + __ fstp(0); + __ ret(kPointerSize); + + __ 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, &runtime_call_clear_stack); + GenerateOperation(masm); + __ mov(Operand(ecx, 0), ebx); + __ mov(Operand(ecx, kIntSize), edx); + __ mov(Operand(ecx, 2 * kIntSize), eax); + __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); + __ ret(kPointerSize); + + __ bind(&runtime_call_clear_stack); + __ fstp(0); + __ bind(&runtime_call); + __ TailCallRuntime(ExternalReference(RuntimeFunction()), 1, 1); +} + + +Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() { + switch (type_) { + // Add more cases when necessary. + case TranscendentalCache::SIN: return Runtime::kMath_sin; + case TranscendentalCache::COS: return Runtime::kMath_cos; + default: + UNIMPLEMENTED(); + return Runtime::kAbort; + } +} + + +void TranscendentalCacheStub::GenerateOperation(MacroAssembler* masm) { + // Only free register is edi. + Label done; + ASSERT(type_ == TranscendentalCache::SIN || + type_ == TranscendentalCache::COS); + // More transcendental types can be added later. + + // 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. + __ 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)); + Label 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); + + // 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. + { + Label 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) + { + Label 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); +} + + // 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. // Trashes edi and ebx. Dest is ecx. Source cannot be ecx or one of the diff --git a/src/ia32/codegen-ia32.h b/src/ia32/codegen-ia32.h index 99dc340b6..b84a6bbaa 100644 --- a/src/ia32/codegen-ia32.h +++ b/src/ia32/codegen-ia32.h @@ -588,6 +588,10 @@ class CodeGenerator: public AstVisitor { // Fast support for number to string. void GenerateNumberToString(ZoneList* args); + // Fast call to transcendental functions. + void GenerateMathSin(ZoneList* args); + void GenerateMathCos(ZoneList* args); + // Simple condition analysis. enum ConditionAnalysis { ALWAYS_TRUE, @@ -655,6 +659,22 @@ class CodeGenerator: public AstVisitor { }; +// Compute a transcendental math function natively, or call the +// TranscendentalCache runtime function. +class TranscendentalCacheStub: public CodeStub { + public: + explicit TranscendentalCacheStub(TranscendentalCache::Type type) + : type_(type) {} + void Generate(MacroAssembler* masm); + private: + TranscendentalCache::Type type_; + Major MajorKey() { return TranscendentalCache; } + int MinorKey() { return type_; } + Runtime::FunctionId RuntimeFunction(); + void GenerateOperation(MacroAssembler* masm); +}; + + // Flag that indicates how to generate code for the stub GenericBinaryOpStub. enum GenericBinaryFlags { NO_GENERIC_BINARY_FLAGS = 0, diff --git a/src/ia32/disasm-ia32.cc b/src/ia32/disasm-ia32.cc index a3b701645..a085900a4 100644 --- a/src/ia32/disasm-ia32.cc +++ b/src/ia32/disasm-ia32.cc @@ -679,6 +679,7 @@ int DisassemblerIA32::MemoryFPUInstruction(int escape_opcode, case 0xDD: switch (regop) { case 0: mnem = "fld_d"; break; + case 2: mnem = "fstp"; break; case 3: mnem = "fstp_d"; break; default: UnimplementedInstruction(); } @@ -720,6 +721,7 @@ int DisassemblerIA32::RegisterFPUInstruction(int escape_opcode, case 0xE1: mnem = "fabs"; break; case 0xE4: mnem = "ftst"; break; case 0xE8: mnem = "fld1"; break; + case 0xEB: mnem = "fldpi"; break; case 0xEE: mnem = "fldz"; break; case 0xF5: mnem = "fprem1"; break; case 0xF7: mnem = "fincstp"; break; diff --git a/src/math.js b/src/math.js index 5745e6179..4c9de6741 100644 --- a/src/math.js +++ b/src/math.js @@ -84,7 +84,7 @@ function MathCeil(x) { // ECMA 262 - 15.8.2.7 function MathCos(x) { if (!IS_NUMBER(x)) x = ToNumber(x); - return %Math_cos(x); + return %_Math_cos(x); } // ECMA 262 - 15.8.2.8 @@ -176,7 +176,7 @@ function MathRound(x) { // ECMA 262 - 15.8.2.16 function MathSin(x) { if (!IS_NUMBER(x)) x = ToNumber(x); - return %Math_sin(x); + return %_Math_sin(x); } // ECMA 262 - 15.8.2.17 diff --git a/src/runtime.cc b/src/runtime.cc index 6459aa78d..6e8503430 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -4638,6 +4638,7 @@ static Object* Runtime_StringCompare(Arguments args) { static Object* Runtime_Math_abs(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); + Counters::math_abs.Increment(); CONVERT_DOUBLE_CHECKED(x, args[0]); return Heap::AllocateHeapNumber(fabs(x)); @@ -4647,6 +4648,7 @@ static Object* Runtime_Math_abs(Arguments args) { static Object* Runtime_Math_acos(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); + Counters::math_acos.Increment(); CONVERT_DOUBLE_CHECKED(x, args[0]); return TranscendentalCache::Get(TranscendentalCache::ACOS, x); @@ -4656,6 +4658,7 @@ static Object* Runtime_Math_acos(Arguments args) { static Object* Runtime_Math_asin(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); + Counters::math_asin.Increment(); CONVERT_DOUBLE_CHECKED(x, args[0]); return TranscendentalCache::Get(TranscendentalCache::ASIN, x); @@ -4665,6 +4668,7 @@ static Object* Runtime_Math_asin(Arguments args) { static Object* Runtime_Math_atan(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); + Counters::math_atan.Increment(); CONVERT_DOUBLE_CHECKED(x, args[0]); return TranscendentalCache::Get(TranscendentalCache::ATAN, x); @@ -4674,6 +4678,7 @@ static Object* Runtime_Math_atan(Arguments args) { static Object* Runtime_Math_atan2(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); + Counters::math_atan2.Increment(); CONVERT_DOUBLE_CHECKED(x, args[0]); CONVERT_DOUBLE_CHECKED(y, args[1]); @@ -4697,6 +4702,7 @@ static Object* Runtime_Math_atan2(Arguments args) { static Object* Runtime_Math_ceil(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); + Counters::math_ceil.Increment(); CONVERT_DOUBLE_CHECKED(x, args[0]); return Heap::NumberFromDouble(ceiling(x)); @@ -4706,6 +4712,7 @@ static Object* Runtime_Math_ceil(Arguments args) { static Object* Runtime_Math_cos(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); + Counters::math_cos.Increment(); CONVERT_DOUBLE_CHECKED(x, args[0]); return TranscendentalCache::Get(TranscendentalCache::COS, x); @@ -4715,6 +4722,7 @@ static Object* Runtime_Math_cos(Arguments args) { static Object* Runtime_Math_exp(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); + Counters::math_exp.Increment(); CONVERT_DOUBLE_CHECKED(x, args[0]); return TranscendentalCache::Get(TranscendentalCache::EXP, x); @@ -4724,6 +4732,7 @@ static Object* Runtime_Math_exp(Arguments args) { static Object* Runtime_Math_floor(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); + Counters::math_floor.Increment(); CONVERT_DOUBLE_CHECKED(x, args[0]); return Heap::NumberFromDouble(floor(x)); @@ -4733,6 +4742,7 @@ static Object* Runtime_Math_floor(Arguments args) { static Object* Runtime_Math_log(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); + Counters::math_log.Increment(); CONVERT_DOUBLE_CHECKED(x, args[0]); return TranscendentalCache::Get(TranscendentalCache::LOG, x); @@ -4773,6 +4783,7 @@ static double powi(double x, int y) { static Object* Runtime_Math_pow(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); + Counters::math_pow.Increment(); CONVERT_DOUBLE_CHECKED(x, args[0]); @@ -4811,6 +4822,7 @@ static Object* Runtime_Math_pow(Arguments args) { static Object* Runtime_Math_round(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); + Counters::math_round.Increment(); CONVERT_DOUBLE_CHECKED(x, args[0]); if (signbit(x) && x >= -0.5) return Heap::minus_zero_value(); @@ -4823,6 +4835,7 @@ static Object* Runtime_Math_round(Arguments args) { static Object* Runtime_Math_sin(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); + Counters::math_sin.Increment(); CONVERT_DOUBLE_CHECKED(x, args[0]); return TranscendentalCache::Get(TranscendentalCache::SIN, x); @@ -4832,6 +4845,7 @@ static Object* Runtime_Math_sin(Arguments args) { static Object* Runtime_Math_sqrt(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); + Counters::math_sqrt.Increment(); CONVERT_DOUBLE_CHECKED(x, args[0]); return Heap::AllocateHeapNumber(sqrt(x)); @@ -4841,6 +4855,7 @@ static Object* Runtime_Math_sqrt(Arguments args) { static Object* Runtime_Math_tan(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); + Counters::math_tan.Increment(); CONVERT_DOUBLE_CHECKED(x, args[0]); return TranscendentalCache::Get(TranscendentalCache::TAN, x); diff --git a/src/serialize.cc b/src/serialize.cc index 0819ec224..590aaa246 100644 --- a/src/serialize.cc +++ b/src/serialize.cc @@ -432,6 +432,10 @@ void ExternalReferenceTable::PopulateTable() { UNCLASSIFIED, 24, "KeyedLookupCache::field_offsets()"); + Add(ExternalReference::transcendental_cache_array_address().address(), + UNCLASSIFIED, + 25, + "TranscendentalCache::caches()"); } diff --git a/src/v8-counters.h b/src/v8-counters.h index eaac2dbbb..2b493fbcd 100644 --- a/src/v8-counters.h +++ b/src/v8-counters.h @@ -169,7 +169,24 @@ namespace internal { SC(regexp_entry_runtime, V8.RegExpEntryRuntime) \ SC(regexp_entry_native, V8.RegExpEntryNative) \ SC(number_to_string_native, V8.NumberToStringNative) \ - SC(number_to_string_runtime, V8.NumberToStringRuntime) + SC(number_to_string_runtime, V8.NumberToStringRuntime) \ + SC(math_abs, V8.MathAbs) \ + SC(math_acos, V8.MathAcos) \ + SC(math_asin, V8.MathAsin) \ + SC(math_atan, V8.MathAtan) \ + SC(math_atan2, V8.MathAtan2) \ + SC(math_ceil, V8.MathCeil) \ + SC(math_cos, V8.MathCos) \ + SC(math_exp, V8.MathExp) \ + SC(math_floor, V8.MathFloor) \ + SC(math_log, V8.MathLog) \ + SC(math_pow, V8.MathPow) \ + SC(math_round, V8.MathRound) \ + SC(math_sin, V8.MathSin) \ + SC(math_sqrt, V8.MathSqrt) \ + SC(math_tan, V8.MathTan) \ + SC(transcendental_cache_hit, V8.TranscendentalCacheHit) \ + SC(transcendental_cache_miss, V8.TranscendentalCacheMiss) // This file contains all the v8 counters that are in use. class Counters : AllStatic { diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc index 28a522f34..e41888367 100644 --- a/src/x64/codegen-x64.cc +++ b/src/x64/codegen-x64.cc @@ -4004,6 +4004,24 @@ void CodeGenerator::GenerateNumberToString(ZoneList* args) { } +void CodeGenerator::GenerateMathSin(ZoneList* args) { + ASSERT_EQ(args->length(), 1); + // Load the argument on the stack and jump to the runtime. + Load(args->at(0)); + Result answer = frame_->CallRuntime(Runtime::kMath_sin, 1); + frame_->Push(&answer); +} + + +void CodeGenerator::GenerateMathCos(ZoneList* args) { + ASSERT_EQ(args->length(), 1); + // Load the argument on the stack and jump to the runtime. + Load(args->at(0)); + Result answer = frame_->CallRuntime(Runtime::kMath_cos, 1); + frame_->Push(&answer); +} + + void CodeGenerator::GenerateStringAdd(ZoneList* args) { ASSERT_EQ(2, args->length()); diff --git a/src/x64/codegen-x64.h b/src/x64/codegen-x64.h index 4593a2839..4b0c77d20 100644 --- a/src/x64/codegen-x64.h +++ b/src/x64/codegen-x64.h @@ -572,7 +572,11 @@ class CodeGenerator: public AstVisitor { // Fast support for number to string. void GenerateNumberToString(ZoneList* args); - // Simple condition analysis. + // Fast call to math functions. + void GenerateMathSin(ZoneList* args); + void GenerateMathCos(ZoneList* args); + +// Simple condition analysis. enum ConditionAnalysis { ALWAYS_TRUE, ALWAYS_FALSE, -- 2.34.1