Revision: 19487
Author:   [email protected]
Date:     Wed Feb 19 13:51:49 2014 UTC
Log:      Harmony: optimize Math.clz32.

[email protected]
BUG=v8:2938
LOG=N

Review URL: https://codereview.chromium.org/172133003
http://code.google.com/p/v8/source/detail?r=19487

Modified:
 /branches/bleeding_edge/src/a64/lithium-a64.cc
 /branches/bleeding_edge/src/a64/lithium-a64.h
 /branches/bleeding_edge/src/a64/lithium-codegen-a64.cc
 /branches/bleeding_edge/src/arm/lithium-arm.cc
 /branches/bleeding_edge/src/arm/lithium-arm.h
 /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
 /branches/bleeding_edge/src/bootstrapper.cc
 /branches/bleeding_edge/src/hydrogen-instructions.cc
 /branches/bleeding_edge/src/hydrogen-instructions.h
 /branches/bleeding_edge/src/hydrogen.cc
 /branches/bleeding_edge/src/ia32/assembler-ia32.cc
 /branches/bleeding_edge/src/ia32/assembler-ia32.h
 /branches/bleeding_edge/src/ia32/disasm-ia32.cc
 /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc
 /branches/bleeding_edge/src/ia32/lithium-ia32.cc
 /branches/bleeding_edge/src/ia32/lithium-ia32.h
 /branches/bleeding_edge/src/objects.h
 /branches/bleeding_edge/src/x64/assembler-x64.cc
 /branches/bleeding_edge/src/x64/assembler-x64.h
 /branches/bleeding_edge/src/x64/disasm-x64.cc
 /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc
 /branches/bleeding_edge/src/x64/lithium-x64.cc
 /branches/bleeding_edge/src/x64/lithium-x64.h
 /branches/bleeding_edge/test/mjsunit/harmony/math-clz32.js

=======================================
--- /branches/bleeding_edge/src/a64/lithium-a64.cc Tue Feb 18 10:45:27 2014 UTC +++ /branches/bleeding_edge/src/a64/lithium-a64.cc Wed Feb 19 13:51:49 2014 UTC
@@ -2377,6 +2377,12 @@
       LOperand* input = UseRegisterAtStart(instr->value());
       return DefineAsRegister(new(zone()) LMathSqrt(input));
     }
+    case kMathClz32: {
+      ASSERT(instr->representation().IsInteger32());
+      ASSERT(instr->value()->representation().IsInteger32());
+      LOperand* input = UseRegisterAtStart(instr->value());
+      return DefineAsRegister(new(zone()) LMathClz32(input));
+    }
     default:
       UNREACHABLE();
       return NULL;
=======================================
--- /branches/bleeding_edge/src/a64/lithium-a64.h Tue Feb 18 10:45:27 2014 UTC +++ /branches/bleeding_edge/src/a64/lithium-a64.h Wed Feb 19 13:51:49 2014 UTC
@@ -130,6 +130,7 @@
   V(MapEnumLength)                              \
   V(MathAbs)                                    \
   V(MathAbsTagged)                              \
+  V(MathClz32)                                  \
   V(MathExp)                                    \
   V(MathFloor)                                  \
   V(MathFloorOfDiv)                             \
@@ -1906,6 +1907,13 @@
 };


+class LMathClz32 V8_FINAL : public LUnaryMathOperation<0> {
+ public:
+  explicit LMathClz32(LOperand* value) : LUnaryMathOperation<0>(value) { }
+  DECLARE_CONCRETE_INSTRUCTION(MathClz32, "math-clz32")
+};
+
+
 class LMathMinMax V8_FINAL : public LTemplateInstruction<1, 2, 0> {
  public:
   LMathMinMax(LOperand* left, LOperand* right) {
=======================================
--- /branches/bleeding_edge/src/a64/lithium-codegen-a64.cc Wed Feb 19 09:38:45 2014 UTC +++ /branches/bleeding_edge/src/a64/lithium-codegen-a64.cc Wed Feb 19 13:51:49 2014 UTC
@@ -3850,6 +3850,13 @@
                    0, 1);
   ASSERT(ToDoubleRegister(instr->result()).Is(d0));
 }
+
+
+void LCodeGen::DoMathClz32(LMathClz32* instr) {
+  Register input = ToRegister32(instr->value());
+  Register result = ToRegister32(instr->result());
+  __ Clz(result, input);
+}


 void LCodeGen::DoMathPowHalf(LMathPowHalf* instr) {
=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.cc Tue Feb 18 10:45:27 2014 UTC +++ /branches/bleeding_edge/src/arm/lithium-arm.cc Wed Feb 19 13:51:49 2014 UTC
@@ -1098,6 +1098,7 @@
     case kMathExp: return DoMathExp(instr);
     case kMathSqrt: return DoMathSqrt(instr);
     case kMathPowHalf: return DoMathPowHalf(instr);
+    case kMathClz32: return DoMathClz32(instr);
     default:
       UNREACHABLE();
       return NULL;
@@ -1137,6 +1138,13 @@
   LOperand* input = UseFixedDouble(instr->value(), d0);
return MarkAsCall(DefineFixedDouble(new(zone()) LMathLog(input), d0), instr);
 }
+
+
+LInstruction* LChunkBuilder::DoMathClz32(HUnaryMathOperation* instr) {
+  LOperand* input = UseRegisterAtStart(instr->value());
+  LMathClz32* result = new(zone()) LMathClz32(input);
+  return DefineAsRegister(result);
+}


 LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) {
=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.h Thu Feb 13 16:09:28 2014 UTC +++ /branches/bleeding_edge/src/arm/lithium-arm.h Wed Feb 19 13:51:49 2014 UTC
@@ -124,6 +124,7 @@
   V(LoadNamedGeneric)                           \
   V(MapEnumLength)                              \
   V(MathAbs)                                    \
+  V(MathClz32)                                  \
   V(MathExp)                                    \
   V(MathFloor)                                  \
   V(MathFloorOfDiv)                             \
@@ -808,6 +809,18 @@
   DECLARE_CONCRETE_INSTRUCTION(MathLog, "math-log")
 };

+
+class LMathClz32 V8_FINAL : public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LMathClz32(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(MathClz32, "math-clz32")
+};
+

 class LMathExp V8_FINAL : public LTemplateInstruction<1, 1, 3> {
  public:
@@ -2606,6 +2619,7 @@
   LInstruction* DoMathExp(HUnaryMathOperation* instr);
   LInstruction* DoMathSqrt(HUnaryMathOperation* instr);
   LInstruction* DoMathPowHalf(HUnaryMathOperation* instr);
+  LInstruction* DoMathClz32(HUnaryMathOperation* instr);

  private:
   enum Status {
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Tue Feb 18 10:45:27 2014 UTC +++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Wed Feb 19 13:51:49 2014 UTC
@@ -3866,6 +3866,13 @@
                    0, 1);
   __ MovFromFloatResult(ToDoubleRegister(instr->result()));
 }
+
+
+void LCodeGen::DoMathClz32(LMathClz32* instr) {
+  Register input = ToRegister(instr->value());
+  Register result = ToRegister(instr->result());
+  __ clz(result, input);
+}


 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
=======================================
--- /branches/bleeding_edge/src/bootstrapper.cc Wed Feb 12 22:04:19 2014 UTC
+++ /branches/bleeding_edge/src/bootstrapper.cc Wed Feb 19 13:51:49 2014 UTC
@@ -231,6 +231,7 @@
   // Installs the contents of the native .js files on the global objects.
   // Used for creating a context from scratch.
   void InstallNativeFunctions();
+  void InstallExperimentalBuiltinFunctionIds();
   void InstallExperimentalNativeFunctions();
Handle<JSFunction> InstallInternalArray(Handle<JSBuiltinsObject> builtins,
                                           const char* name,
@@ -2060,7 +2061,7 @@
   }

   InstallExperimentalNativeFunctions();
-
+  InstallExperimentalBuiltinFunctionIds();
   return true;
 }

@@ -2108,6 +2109,15 @@
   FUNCTIONS_WITH_ID_LIST(INSTALL_BUILTIN_ID)
 #undef INSTALL_BUILTIN_ID
 }
+
+
+void Genesis::InstallExperimentalBuiltinFunctionIds() {
+  HandleScope scope(isolate());
+  if (FLAG_harmony_maths) {
+ Handle<JSObject> holder = ResolveBuiltinIdHolder(native_context(), "Math");
+    InstallBuiltinFunctionId(holder, "clz32", kMathClz32);
+  }
+}


 // Do not forget to update macros.py with named constant
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.cc Tue Feb 18 12:19:32 2014 UTC +++ /branches/bleeding_edge/src/hydrogen-instructions.cc Wed Feb 19 13:51:49 2014 UTC
@@ -1147,6 +1147,7 @@
     case kMathExp: return "exp";
     case kMathSqrt: return "sqrt";
     case kMathPowHalf: return "pow-half";
+    case kMathClz32: return "clz32";
     default:
       UNREACHABLE();
       return NULL;
@@ -1156,6 +1157,7 @@

 Range* HUnaryMathOperation::InferRange(Zone* zone) {
   Representation r = representation();
+  if (op() == kMathClz32) return new(zone) Range(0, 32);
   if (r.IsSmiOrInteger32() && value()->HasRange()) {
     if (op() == kMathAbs) {
       int upper = value()->range()->upper();
@@ -3925,6 +3927,8 @@
         case kMathRound:
         case kMathFloor:
           return H_CONSTANT_DOUBLE(d);
+        case kMathClz32:
+          return H_CONSTANT_INT(32);
         default:
           UNREACHABLE();
           break;
@@ -3950,6 +3954,11 @@
         return H_CONSTANT_DOUBLE(std::floor(d + 0.5));
       case kMathFloor:
         return H_CONSTANT_DOUBLE(std::floor(d));
+      case kMathClz32: {
+        uint32_t i = static_cast<uint32_t>(constant->Integer32Value());
+        return H_CONSTANT_INT(
+            (i == 0) ? 32 : CompilerIntrinsics::CountLeadingZeros(i));
+      }
       default:
         UNREACHABLE();
         break;
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.h Fri Feb 14 14:58:05 2014 UTC +++ /branches/bleeding_edge/src/hydrogen-instructions.h Wed Feb 19 13:51:49 2014 UTC
@@ -2600,6 +2600,8 @@
           return Representation::Double();
         case kMathAbs:
           return representation();
+        case kMathClz32:
+          return Representation::Integer32();
         default:
           UNREACHABLE();
           return Representation::None();
@@ -2631,6 +2633,7 @@
     switch (op) {
       case kMathFloor:
       case kMathRound:
+      case kMathClz32:
         set_representation(Representation::Integer32());
         break;
       case kMathAbs:
=======================================
--- /branches/bleeding_edge/src/hydrogen.cc     Tue Feb 18 12:19:32 2014 UTC
+++ /branches/bleeding_edge/src/hydrogen.cc     Wed Feb 19 13:51:49 2014 UTC
@@ -7459,6 +7459,7 @@
     case kMathAbs:
     case kMathSqrt:
     case kMathLog:
+    case kMathClz32:
       if (expr->arguments()->length() == 1) {
         HValue* argument = Pop();
         Drop(2);  // Receiver and function.
@@ -7529,6 +7530,7 @@
     case kMathAbs:
     case kMathSqrt:
     case kMathLog:
+    case kMathClz32:
       if (argument_count == 2) {
         HValue* argument = Pop();
         Drop(2);  // Receiver and function.
=======================================
--- /branches/bleeding_edge/src/ia32/assembler-ia32.cc Mon Nov 18 15:24:41 2013 UTC +++ /branches/bleeding_edge/src/ia32/assembler-ia32.cc Wed Feb 19 13:51:49 2014 UTC
@@ -1257,6 +1257,14 @@
   EMIT(0xAB);
   emit_operand(src, dst);
 }
+
+
+void Assembler::bsr(Register dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  EMIT(0x0F);
+  EMIT(0xBD);
+  emit_operand(dst, src);
+}


 void Assembler::hlt() {
=======================================
--- /branches/bleeding_edge/src/ia32/assembler-ia32.h Mon Nov 25 14:07:05 2013 UTC +++ /branches/bleeding_edge/src/ia32/assembler-ia32.h Wed Feb 19 13:51:49 2014 UTC
@@ -882,6 +882,8 @@
   void bt(const Operand& dst, Register src);
   void bts(Register dst, Register src) { bts(Operand(dst), src); }
   void bts(const Operand& dst, Register src);
+  void bsr(Register dst, Register src) { bsr(dst, Operand(src)); }
+  void bsr(Register dst, const Operand& src);

   // Miscellaneous
   void hlt();
=======================================
--- /branches/bleeding_edge/src/ia32/disasm-ia32.cc Thu Jan 9 15:20:25 2014 UTC +++ /branches/bleeding_edge/src/ia32/disasm-ia32.cc Wed Feb 19 13:51:49 2014 UTC
@@ -881,6 +881,7 @@
     case 0xAD: return "shrd";
     case 0xAC: return "shrd";  // 3-operand version.
     case 0xAB: return "bts";
+    case 0xBD: return "bsr";
     default: return NULL;
   }
 }
@@ -1096,22 +1097,26 @@
             data += SetCC(data);
           } else if ((f0byte & 0xF0) == 0x40) {
             data += CMov(data);
-          } else {
+          } else if (f0byte == 0xAB || f0byte == 0xA5 || f0byte == 0xAD) {
+            // shrd, shld, bts
             data += 2;
-            if (f0byte == 0xAB || f0byte == 0xA5 || f0byte == 0xAD) {
-              // shrd, shld, bts
-              AppendToBuffer("%s ", f0mnem);
-              int mod, regop, rm;
-              get_modrm(*data, &mod, &regop, &rm);
-              data += PrintRightOperand(data);
-              if (f0byte == 0xAB) {
-                AppendToBuffer(",%s", NameOfCPURegister(regop));
-              } else {
-                AppendToBuffer(",%s,cl", NameOfCPURegister(regop));
-              }
+            AppendToBuffer("%s ", f0mnem);
+            int mod, regop, rm;
+            get_modrm(*data, &mod, &regop, &rm);
+            data += PrintRightOperand(data);
+            if (f0byte == 0xAB) {
+              AppendToBuffer(",%s", NameOfCPURegister(regop));
             } else {
-              UnimplementedInstruction();
+              AppendToBuffer(",%s,cl", NameOfCPURegister(regop));
             }
+          } else if (f0byte == 0xBD) {
+            data += 2;
+            int mod, regop, rm;
+            get_modrm(*data, &mod, &regop, &rm);
+            AppendToBuffer("%s %s,", f0mnem, NameOfCPURegister(regop));
+            data += PrintRightOperand(data);
+          } else {
+            UnimplementedInstruction();
           }
         }
         break;
@@ -1606,13 +1611,13 @@
             get_modrm(*data, &mod, &regop, &rm);
             AppendToBuffer("cvtss2sd %s,", NameOfXMMRegister(regop));
             data += PrintRightXMMOperand(data);
-          } else  if (b2 == 0x6F) {
+          } else if (b2 == 0x6F) {
             data += 3;
             int mod, regop, rm;
             get_modrm(*data, &mod, &regop, &rm);
             AppendToBuffer("movdqu %s,", NameOfXMMRegister(regop));
             data += PrintRightXMMOperand(data);
-          } else  if (b2 == 0x7F) {
+          } else if (b2 == 0x7F) {
             AppendToBuffer("movdqu ");
             data += 3;
             int mod, regop, rm;
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Tue Feb 18 10:45:27 2014 UTC +++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Wed Feb 19 13:51:49 2014 UTC
@@ -4121,6 +4121,21 @@
   __ add(Operand(esp), Immediate(kDoubleSize));
   __ bind(&done);
 }
+
+
+void LCodeGen::DoMathClz32(LMathClz32* instr) {
+  CpuFeatureScope scope(masm(), SSE2);
+  Register input = ToRegister(instr->value());
+  Register result = ToRegister(instr->result());
+  Label not_zero_input;
+  __ bsr(result, input);
+
+  __ j(not_zero, &not_zero_input);
+  __ Set(result, Immediate(63));  // 63^31 == 32
+
+  __ bind(&not_zero_input);
+  __ xor_(result, Immediate(31));  // for x in [0..31], 31^x == 31-x.
+}


 void LCodeGen::DoMathExp(LMathExp* instr) {
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.cc Tue Feb 18 10:45:27 2014 UTC +++ /branches/bleeding_edge/src/ia32/lithium-ia32.cc Wed Feb 19 13:51:49 2014 UTC
@@ -1184,6 +1184,7 @@
     case kMathExp: return DoMathExp(instr);
     case kMathSqrt: return DoMathSqrt(instr);
     case kMathPowHalf: return DoMathPowHalf(instr);
+    case kMathClz32: return DoMathClz32(instr);
     default:
       UNREACHABLE();
       return NULL;
@@ -1220,6 +1221,13 @@
   LOperand* input = UseRegisterAtStart(instr->value());
   return MarkAsCall(DefineSameAsFirst(new(zone()) LMathLog(input)), instr);
 }
+
+
+LInstruction* LChunkBuilder::DoMathClz32(HUnaryMathOperation* instr) {
+  LOperand* input = UseRegisterAtStart(instr->value());
+  LMathClz32* result = new(zone()) LMathClz32(input);
+  return DefineAsRegister(result);
+}


 LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) {
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.h Thu Jan 30 12:52:49 2014 UTC +++ /branches/bleeding_edge/src/ia32/lithium-ia32.h Wed Feb 19 13:51:49 2014 UTC
@@ -126,6 +126,7 @@
   V(LoadRoot)                                   \
   V(MapEnumLength)                              \
   V(MathAbs)                                    \
+  V(MathClz32)                                  \
   V(MathExp)                                    \
   V(MathFloor)                                  \
   V(MathFloorOfDiv)                             \
@@ -781,6 +782,18 @@
   DECLARE_CONCRETE_INSTRUCTION(MathLog, "math-log")
 };

+
+class LMathClz32 V8_FINAL : public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LMathClz32(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(MathClz32, "math-clz32")
+};
+

 class LMathExp V8_FINAL : public LTemplateInstruction<1, 1, 2> {
  public:
@@ -2612,6 +2625,7 @@
   LInstruction* DoMathExp(HUnaryMathOperation* instr);
   LInstruction* DoMathSqrt(HUnaryMathOperation* instr);
   LInstruction* DoMathPowHalf(HUnaryMathOperation* instr);
+  LInstruction* DoMathClz32(HUnaryMathOperation* instr);

  private:
   enum Status {
=======================================
--- /branches/bleeding_edge/src/objects.h       Wed Feb 19 09:43:45 2014 UTC
+++ /branches/bleeding_edge/src/objects.h       Wed Feb 19 13:51:49 2014 UTC
@@ -6617,7 +6617,9 @@
 #undef DECLARE_FUNCTION_ID
   // Fake id for a special case of Math.pow. Note, it continues the
   // list of math functions.
-  kMathPowHalf
+  kMathPowHalf,
+  // Installed only on --harmony-maths.
+  kMathClz32
 };


=======================================
--- /branches/bleeding_edge/src/x64/assembler-x64.cc Fri Jan 24 01:45:53 2014 UTC +++ /branches/bleeding_edge/src/x64/assembler-x64.cc Wed Feb 19 13:51:49 2014 UTC
@@ -748,6 +748,15 @@
   emit(0xAB);
   emit_operand(src, dst);
 }
+
+
+void Assembler::bsrl(Register dst, Register src) {
+  EnsureSpace ensure_space(this);
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0xBD);
+  emit_modrm(dst, src);
+}


 void Assembler::call(Label* L) {
=======================================
--- /branches/bleeding_edge/src/x64/assembler-x64.h Wed Feb 12 09:19:30 2014 UTC +++ /branches/bleeding_edge/src/x64/assembler-x64.h Wed Feb 19 13:51:49 2014 UTC
@@ -1194,6 +1194,7 @@
   // Bit operations.
   void bt(const Operand& dst, Register src);
   void bts(const Operand& dst, Register src);
+  void bsrl(Register dst, Register src);

   // Miscellaneous
   void clc();
=======================================
--- /branches/bleeding_edge/src/x64/disasm-x64.cc Mon Feb 3 08:13:12 2014 UTC +++ /branches/bleeding_edge/src/x64/disasm-x64.cc Wed Feb 19 13:51:49 2014 UTC
@@ -1326,6 +1326,12 @@
     } else {
       AppendToBuffer(",%s,cl", NameOfCPURegister(regop));
     }
+  } else if (opcode == 0xBD) {
+    AppendToBuffer("%s%c ", mnemonic, operand_size_code());
+    int mod, regop, rm;
+    get_modrm(*current, &mod, &regop, &rm);
+    AppendToBuffer("%s,", NameOfCPURegister(regop));
+    current += PrintRightOperand(current);
   } else {
     UnimplementedInstruction();
   }
@@ -1368,6 +1374,8 @@
       return "movzxb";
     case 0xB7:
       return "movzxw";
+    case 0xBD:
+      return "bsr";
     case 0xBE:
       return "movsxb";
     case 0xBF:
=======================================
--- /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Tue Feb 18 10:45:27 2014 UTC +++ /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Wed Feb 19 13:51:49 2014 UTC
@@ -3727,6 +3727,20 @@
   __ addq(rsp, Immediate(kDoubleSize));
   __ bind(&done);
 }
+
+
+void LCodeGen::DoMathClz32(LMathClz32* instr) {
+  Register input = ToRegister(instr->value());
+  Register result = ToRegister(instr->result());
+  Label not_zero_input;
+  __ bsrl(result, input);
+
+  __ j(not_zero, &not_zero_input);
+  __ Set(result, 63);  // 63^31 == 32
+
+  __ bind(&not_zero_input);
+  __ xorl(result, Immediate(31));  // for x in [0..31], 31^x == 31-x.
+}


 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
=======================================
--- /branches/bleeding_edge/src/x64/lithium-x64.cc Tue Feb 18 10:45:27 2014 UTC +++ /branches/bleeding_edge/src/x64/lithium-x64.cc Wed Feb 19 13:51:49 2014 UTC
@@ -1106,6 +1106,7 @@
     case kMathExp: return DoMathExp(instr);
     case kMathSqrt: return DoMathSqrt(instr);
     case kMathPowHalf: return DoMathPowHalf(instr);
+    case kMathClz32: return DoMathClz32(instr);
     default:
       UNREACHABLE();
       return NULL;
@@ -1141,6 +1142,13 @@
   LOperand* input = UseRegisterAtStart(instr->value());
   return MarkAsCall(DefineSameAsFirst(new(zone()) LMathLog(input)), instr);
 }
+
+
+LInstruction* LChunkBuilder::DoMathClz32(HUnaryMathOperation* instr) {
+  LOperand* input = UseRegisterAtStart(instr->value());
+  LMathClz32* result = new(zone()) LMathClz32(input);
+  return DefineAsRegister(result);
+}


 LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) {
=======================================
--- /branches/bleeding_edge/src/x64/lithium-x64.h Thu Jan 30 12:52:49 2014 UTC +++ /branches/bleeding_edge/src/x64/lithium-x64.h Wed Feb 19 13:51:49 2014 UTC
@@ -124,6 +124,7 @@
   V(LoadNamedGeneric)                           \
   V(MapEnumLength)                              \
   V(MathAbs)                                    \
+  V(MathClz32)                                  \
   V(MathExp)                                    \
   V(MathFloor)                                  \
   V(MathFloorOfDiv)                             \
@@ -759,6 +760,18 @@
   DECLARE_CONCRETE_INSTRUCTION(MathLog, "math-log")
 };

+
+class LMathClz32 V8_FINAL : public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LMathClz32(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(MathClz32, "math-clz32")
+};
+

 class LMathExp V8_FINAL : public LTemplateInstruction<1, 1, 2> {
  public:
@@ -2529,6 +2542,7 @@
   LInstruction* DoMathExp(HUnaryMathOperation* instr);
   LInstruction* DoMathSqrt(HUnaryMathOperation* instr);
   LInstruction* DoMathPowHalf(HUnaryMathOperation* instr);
+  LInstruction* DoMathClz32(HUnaryMathOperation* instr);

  private:
   enum Status {
=======================================
--- /branches/bleeding_edge/test/mjsunit/harmony/math-clz32.js Tue Feb 18 10:49:35 2014 UTC +++ /branches/bleeding_edge/test/mjsunit/harmony/math-clz32.js Wed Feb 19 13:51:49 2014 UTC
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.

-// Flags: --harmony-maths
+// Flags: --harmony-maths --allow-natives-syntax

[NaN, Infinity, -Infinity, 0, -0, "abc", "Infinity", "-Infinity", {}].forEach(
   function(x) {
@@ -18,11 +18,19 @@
   return 32;
 }

-var max = Math.pow(2, 40);
-for (var x = 0; x < max; x = x * 1.01 + 1) {
-  assertEquals(testclz(x), Math.clz32(x));
-  assertEquals(testclz(-x), Math.clz32(-x));
- assertEquals(testclz(x), Math.clz32({ valueOf: function() { return x; } }));
-  assertEquals(testclz(-x),
-               Math.clz32({ toString: function() { return -x; } }));
+
+function f(e) {
+  var max = Math.pow(2, e);
+  for (var x = 0; x < max; x = x * 1.01 + 1) {
+    assertEquals(testclz(x), Math.clz32(x));
+    assertEquals(testclz(-x), Math.clz32(-x));
+ assertEquals(testclz(x), Math.clz32({ valueOf: function() { return x; } }));
+    assertEquals(testclz(-x),
+                 Math.clz32({ toString: function() { return -x; } }));
+  }
 }
+
+f(5);
+f(5);
+%OptimizeFunctionOnNextCall(f);
+f(40);

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to