Revision: 3929
Author: [email protected]
Date: Tue Feb 23 02:29:02 2010
Log: IA32: Native access to TranscendentalCache for sin/cos.

Review URL: http://codereview.chromium.org/652041
http://code.google.com/p/v8/source/detail?r=3929

Modified:
 /branches/bleeding_edge/src/arm/codegen-arm.cc
 /branches/bleeding_edge/src/arm/codegen-arm.h
 /branches/bleeding_edge/src/assembler.cc
 /branches/bleeding_edge/src/assembler.h
 /branches/bleeding_edge/src/code-stubs.h
 /branches/bleeding_edge/src/codegen.cc
 /branches/bleeding_edge/src/heap.h
 /branches/bleeding_edge/src/ia32/assembler-ia32.cc
 /branches/bleeding_edge/src/ia32/assembler-ia32.h
 /branches/bleeding_edge/src/ia32/codegen-ia32.cc
 /branches/bleeding_edge/src/ia32/codegen-ia32.h
 /branches/bleeding_edge/src/ia32/disasm-ia32.cc
 /branches/bleeding_edge/src/math.js
 /branches/bleeding_edge/src/runtime.cc
 /branches/bleeding_edge/src/serialize.cc
 /branches/bleeding_edge/src/v8-counters.h
 /branches/bleeding_edge/src/x64/codegen-x64.cc
 /branches/bleeding_edge/src/x64/codegen-x64.h

=======================================
--- /branches/bleeding_edge/src/arm/codegen-arm.cc      Fri Feb 19 06:52:39 2010
+++ /branches/bleeding_edge/src/arm/codegen-arm.cc      Tue Feb 23 02:29:02 2010
@@ -3626,6 +3626,24 @@
   frame_->CallRuntime(Runtime::kNumberToString, 1);
   frame_->EmitPush(r0);
 }
+
+
+void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* 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<Expression*>* 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<Expression*>* args) {
=======================================
--- /branches/bleeding_edge/src/arm/codegen-arm.h       Fri Feb 19 06:52:39 2010
+++ /branches/bleeding_edge/src/arm/codegen-arm.h       Tue Feb 23 02:29:02 2010
@@ -393,6 +393,10 @@
   // Fast support for number to string.
   void GenerateNumberToString(ZoneList<Expression*>* args);

+  // Fast call to sine function.
+  void GenerateMathSin(ZoneList<Expression*>* args);
+  void GenerateMathCos(ZoneList<Expression*>* args);
+
   // Simple condition analysis.
   enum ConditionAnalysis {
     ALWAYS_TRUE,
=======================================
--- /branches/bleeding_edge/src/assembler.cc    Mon Feb  8 05:44:49 2010
+++ /branches/bleeding_edge/src/assembler.cc    Tue Feb 23 02:29:02 2010
@@ -577,6 +577,11 @@
 ExternalReference ExternalReference::random_positive_smi_function() {
   return ExternalReference(Redirect(FUNCTION_ADDR(V8::RandomPositiveSmi)));
 }
+
+
+ExternalReference ExternalReference::transcendental_cache_array_address() {
+  return ExternalReference(TranscendentalCache::cache_array_address());
+}


 ExternalReference ExternalReference::keyed_lookup_cache_keys() {
=======================================
--- /branches/bleeding_edge/src/assembler.h     Mon Feb  8 05:44:49 2010
+++ /branches/bleeding_edge/src/assembler.h     Tue Feb 23 02:29:02 2010
@@ -400,6 +400,7 @@

   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();
=======================================
--- /branches/bleeding_edge/src/code-stubs.h    Tue Feb 16 01:41:11 2010
+++ /branches/bleeding_edge/src/code-stubs.h    Tue Feb 23 02:29:02 2010
@@ -48,6 +48,7 @@
   V(FastNewClosure)                      \
   V(FastNewContext)                      \
   V(FastCloneShallowArray)               \
+  V(TranscendentalCache)                 \
   V(GenericUnaryOp)                      \
   V(RevertToNumber)                      \
   V(ToBoolean)                           \
=======================================
--- /branches/bleeding_edge/src/codegen.cc      Fri Feb 19 06:52:39 2010
+++ /branches/bleeding_edge/src/codegen.cc      Tue Feb 23 02:29:02 2010
@@ -379,6 +379,8 @@
   {&CodeGenerator::GenerateStringCompare, "_StringCompare"},
   {&CodeGenerator::GenerateRegExpExec, "_RegExpExec"},
   {&CodeGenerator::GenerateNumberToString, "_NumberToString"},
+  {&CodeGenerator::GenerateMathSin, "_Math_sin"},
+  {&CodeGenerator::GenerateMathCos, "_Math_cos"},
 };


=======================================
--- /branches/bleeding_edge/src/heap.h  Mon Feb 22 03:42:46 2010
+++ /branches/bleeding_edge/src/heap.h  Tue Feb 23 02:29:02 2010
@@ -1610,6 +1610,7 @@
     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 @@
       elements_[hash].in[1] = c.integers[1];
       elements_[hash].output = heap_number;
     }
+    Counters::transcendental_cache_miss.Increment();
     return heap_number;
   }

@@ -1659,6 +1661,17 @@
     hash ^= hash >> 8;
     return (hash & (kCacheSize - 1));
   }
+
+  static Address cache_array_address() {
+    // Used to create an external reference.
+    return reinterpret_cast<Address>(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_;
=======================================
--- /branches/bleeding_edge/src/ia32/assembler-ia32.cc Thu Feb 4 13:32:02 2010 +++ /branches/bleeding_edge/src/ia32/assembler-ia32.cc Tue Feb 23 02:29:02 2010
@@ -1635,6 +1635,13 @@
   last_pc_ = pc_;
   emit_farith(0xD9, 0xC0, i);
 }
+
+
+void Assembler::fstp(int i) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit_farith(0xDD, 0xD8, i);
+}


 void Assembler::fld1() {
@@ -1643,6 +1650,14 @@
   EMIT(0xD9);
   EMIT(0xE8);
 }
+
+
+void Assembler::fldpi() {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xD9);
+  EMIT(0xEB);
+}


 void Assembler::fldz() {
@@ -1683,6 +1698,14 @@
   EMIT(0xDD);
   emit_operand(ebx, 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) {
=======================================
--- /branches/bleeding_edge/src/ia32/assembler-ia32.h Fri Feb 12 03:55:04 2010 +++ /branches/bleeding_edge/src/ia32/assembler-ia32.h Tue Feb 23 02:29:02 2010
@@ -668,6 +668,7 @@
   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> code, RelocInfo::Mode rmode);

   // Jumps
@@ -683,15 +684,18 @@

   // 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);
=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.cc Fri Feb 19 07:04:16 2010 +++ /branches/bleeding_edge/src/ia32/codegen-ia32.cc Tue Feb 23 02:29:02 2010
@@ -5823,6 +5823,24 @@
   Result result = frame_->CallStub(&stub, 1);
   frame_->Push(&result);
 }
+
+
+void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* 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<Expression*>* 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) {
@@ -8121,6 +8139,212 @@
     __ ret(0);
   }
 }
+
+
+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<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.
+  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
=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.h     Fri Feb 19 07:04:16 2010
+++ /branches/bleeding_edge/src/ia32/codegen-ia32.h     Tue Feb 23 02:29:02 2010
@@ -588,6 +588,10 @@
   // Fast support for number to string.
   void GenerateNumberToString(ZoneList<Expression*>* args);

+  // Fast call to transcendental functions.
+  void GenerateMathSin(ZoneList<Expression*>* args);
+  void GenerateMathCos(ZoneList<Expression*>* args);
+
   // Simple condition analysis.
   enum ConditionAnalysis {
     ALWAYS_TRUE,
@@ -655,6 +659,22 @@
 };


+// 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,
=======================================
--- /branches/bleeding_edge/src/ia32/disasm-ia32.cc     Mon Feb 15 23:54:28 2010
+++ /branches/bleeding_edge/src/ia32/disasm-ia32.cc     Tue Feb 23 02:29:02 2010
@@ -679,6 +679,7 @@

     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 @@
             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;
=======================================
--- /branches/bleeding_edge/src/math.js Wed Feb 17 03:26:00 2010
+++ /branches/bleeding_edge/src/math.js Tue Feb 23 02:29:02 2010
@@ -84,7 +84,7 @@
 // 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 @@
 // 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
=======================================
--- /branches/bleeding_edge/src/runtime.cc      Fri Feb 19 09:11:47 2010
+++ /branches/bleeding_edge/src/runtime.cc      Tue Feb 23 02:29:02 2010
@@ -4638,6 +4638,7 @@
 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_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_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_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_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_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_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_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_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_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 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_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_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_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_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);
=======================================
--- /branches/bleeding_edge/src/serialize.cc    Mon Feb 22 03:42:46 2010
+++ /branches/bleeding_edge/src/serialize.cc    Tue Feb 23 02:29:02 2010
@@ -432,6 +432,10 @@
       UNCLASSIFIED,
       24,
       "KeyedLookupCache::field_offsets()");
+  Add(ExternalReference::transcendental_cache_array_address().address(),
+      UNCLASSIFIED,
+      25,
+      "TranscendentalCache::caches()");
 }


=======================================
--- /branches/bleeding_edge/src/v8-counters.h   Tue Feb 16 01:41:11 2010
+++ /branches/bleeding_edge/src/v8-counters.h   Tue Feb 23 02:29:02 2010
@@ -169,7 +169,24 @@
   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 {
=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.cc      Fri Feb 19 06:52:39 2010
+++ /branches/bleeding_edge/src/x64/codegen-x64.cc      Tue Feb 23 02:29:02 2010
@@ -4002,6 +4002,24 @@
   Result answer = frame_->CallRuntime(Runtime::kNumberToString, 1);
   frame_->Push(&answer);
 }
+
+
+void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* 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<Expression*>* 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<Expression*>* args) {
=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.h       Fri Feb 19 06:52:39 2010
+++ /branches/bleeding_edge/src/x64/codegen-x64.h       Tue Feb 23 02:29:02 2010
@@ -572,7 +572,11 @@
   // Fast support for number to string.
   void GenerateNumberToString(ZoneList<Expression*>* args);

-  // Simple condition analysis.
+  // Fast call to math functions.
+  void GenerateMathSin(ZoneList<Expression*>* args);
+  void GenerateMathCos(ZoneList<Expression*>* args);
+
+// Simple condition analysis.
   enum ConditionAnalysis {
     ALWAYS_TRUE,
     ALWAYS_FALSE,

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to