Revision: 14450
Author:   [email protected]
Date:     Fri Apr 26 01:52:35 2013
Log:      Implement support for Math.imul in Crankshaft.

[email protected]
TEST=mjsunit/math-imul

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

Added:
 /branches/bleeding_edge/test/mjsunit/math-imul.js
Modified:
 /branches/bleeding_edge/src/hydrogen-instructions.h
 /branches/bleeding_edge/src/hydrogen.cc
 /branches/bleeding_edge/src/math.js
 /branches/bleeding_edge/src/objects.h
 /branches/bleeding_edge/src/runtime.cc
 /branches/bleeding_edge/src/runtime.h

=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/math-imul.js Fri Apr 26 01:52:35 2013
@@ -0,0 +1,148 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax --max-opt-count=1000
+
+var imul_func = Math.imul;
+function imul_polyfill(a, b) {
+  var ah  = (a >>> 16) & 0xffff;
+  var al = a & 0xffff;
+  var bh  = (b >>> 16) & 0xffff;
+  var bl = b & 0xffff;
+  return ((al * bl) + (((ah * bl + al * bh) << 16) >>> 0) | 0);
+}
+
+function TestMathImul(expected, a, b) {
+  function imul_meth_closure(a, b) { return Math.imul(a, b); }
+  function imul_func_closure(a, b) { return imul_func(a, b); }
+
+  // Test reference implementation.
+  assertEquals(expected, imul_polyfill(a, b));
+
+  // Test direct method call.
+  assertEquals(expected, Math.imul(a, b));
+
+  // Test direct function call.
+  assertEquals(expected, imul_func(a, b));
+
+  // Test optimized method call inside closure.
+  assertEquals(expected, imul_meth_closure(a, b));
+  assertEquals(expected, imul_meth_closure(a, b));
+  %OptimizeFunctionOnNextCall(imul_meth_closure);
+  assertEquals(expected, imul_meth_closure(a, b));
+
+  // Test optimized function call inside closure.
+  assertEquals(expected, imul_func_closure(a, b));
+  assertEquals(expected, imul_func_closure(a, b));
+  %OptimizeFunctionOnNextCall(imul_func_closure);
+  assertEquals(expected, imul_func_closure(a, b));
+
+  // Deoptimize closures and forget type feedback.
+  %DeoptimizeFunction(imul_meth_closure);
+  %DeoptimizeFunction(imul_func_closure);
+  %ClearFunctionTypeFeedback(imul_meth_closure);
+  %ClearFunctionTypeFeedback(imul_func_closure);
+}
+
+TestMathImul(8, 2, 4);
+TestMathImul(-8, -1, 8);
+TestMathImul(4, -2, -2);
+TestMathImul(-5, 0xffffffff, 5);
+TestMathImul(-10, 0xfffffffe, 5);
+
+TestMathImul(0, false, 7);
+TestMathImul(0, 7, false);
+TestMathImul(0, false, false);
+
+TestMathImul(7, true, 7);
+TestMathImul(7, 7, true);
+TestMathImul(1, true, true);
+
+TestMathImul(0, false, true);
+TestMathImul(0, true, false);
+
+TestMathImul(0, undefined, 7);
+TestMathImul(0, 7, undefined);
+TestMathImul(0, undefined, undefined);
+
+TestMathImul(0, -0, 7);
+TestMathImul(0, 7, -0);
+
+TestMathImul(0, 0.1, 7);
+TestMathImul(0, 7, 0.1);
+TestMathImul(0, 0.9, 7);
+TestMathImul(0, 7, 0.9);
+TestMathImul(7, 1.1, 7);
+TestMathImul(7, 7, 1.1);
+TestMathImul(7, 1.9, 7);
+TestMathImul(7, 7, 1.9);
+
+TestMathImul(0, "str", 7);
+TestMathImul(0, 7, "str");
+
+TestMathImul(0, {}, 7);
+TestMathImul(0, 7, {});
+
+TestMathImul(0, [], 7);
+TestMathImul(0, 7, []);
+
+// 2^30 is a smi boundary on arm and ia32.
+var two_30 = 1 << 30;
+
+TestMathImul(-two_30, two_30, 7);
+TestMathImul(-two_30, 7, two_30);
+TestMathImul(0, two_30, two_30);
+
+TestMathImul(two_30, -two_30, 7);
+TestMathImul(two_30, 7, -two_30);
+TestMathImul(0, -two_30, -two_30);
+
+// 2^31 is a smi boundary on x64.
+var two_31 = 2 * two_30;
+
+TestMathImul(-two_31, two_31, 7);
+TestMathImul(-two_31, 7, two_31);
+TestMathImul(0, two_31, two_31);
+
+TestMathImul(-two_31, -two_31, 7);
+TestMathImul(-two_31, 7, -two_31);
+TestMathImul(0, -two_31, -two_31);
+
+// 2^31 - 1 is the largest int32 value.
+var max_val = two_31 - 1;
+
+TestMathImul(two_31 - 7, max_val, 7);
+TestMathImul(two_31 - 7, 7, max_val);
+TestMathImul(1, max_val, max_val);
+
+// 2^16 is a boundary value that overflows when squared.
+var two_16 = 1 << 16;
+
+TestMathImul(0, two_16, two_16);
+TestMathImul(-two_16, two_16 - 1, two_16);
+TestMathImul(-two_16, two_16, two_16 - 1);
+TestMathImul(-2 * two_16 + 1, two_16 - 1, two_16 - 1);
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.h Fri Apr 26 01:47:02 2013 +++ /branches/bleeding_edge/src/hydrogen-instructions.h Fri Apr 26 01:52:35 2013
@@ -4421,6 +4421,17 @@
                            HValue* context,
                            HValue* left,
                            HValue* right);
+
+  static HInstruction* NewImul(Zone* zone,
+                               HValue* context,
+                               HValue* left,
+                               HValue* right) {
+    HMul* mul = new(zone) HMul(context, left, right);
+    // TODO(mstarzinger): Prevent bailout on minus zero for imul.
+    mul->AssumeRepresentation(Representation::Integer32());
+    mul->ClearFlag(HValue::kCanOverflow);
+    return mul;
+  }

   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);

=======================================
--- /branches/bleeding_edge/src/hydrogen.cc     Fri Apr 26 01:49:20 2013
+++ /branches/bleeding_edge/src/hydrogen.cc     Fri Apr 26 01:52:35 2013
@@ -8942,6 +8942,18 @@
         ast_context()->ReturnInstruction(op, expr->id());
         return true;
       }
+      break;
+    case kMathImul:
+      if (expr->arguments()->length() == 2) {
+        HValue* right = Pop();
+        HValue* left = Pop();
+        Drop(1);  // Receiver.
+        HValue* context = environment()->LookupContext();
+        HInstruction* op = HMul::NewImul(zone(), context, left, right);
+        if (drop_extra) Drop(1);  // Optionally drop the function.
+        ast_context()->ReturnInstruction(op, expr->id());
+        return true;
+      }
       break;
     default:
       // Not supported for inlining yet.
@@ -9089,6 +9101,18 @@
         ast_context()->ReturnInstruction(result, expr->id());
         return true;
       }
+      break;
+    case kMathImul:
+      if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) {
+        AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
+        HValue* right = Pop();
+        HValue* left = Pop();
+        Drop(1);  // Receiver.
+        HValue* context = environment()->LookupContext();
+        HInstruction* result = HMul::NewImul(zone(), context, left, right);
+        ast_context()->ReturnInstruction(result, expr->id());
+        return true;
+      }
       break;
     default:
       // Not yet supported for inlining.
=======================================
--- /branches/bleeding_edge/src/math.js Thu Apr 11 05:15:25 2013
+++ /branches/bleeding_edge/src/math.js Fri Apr 26 01:52:35 2013
@@ -212,6 +212,13 @@
   if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
   return %_MathTan(x);
 }
+
+// Non-standard extension.
+function MathImul(x, y) {
+  if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
+  if (!IS_NUMBER(y)) y = NonNumberToNumber(y);
+  return %NumberImul(x, y);
+}


 // -------------------------------------------------------------------
@@ -283,7 +290,8 @@
     "atan2", MathAtan2,
     "pow", MathPow,
     "max", MathMax,
-    "min", MathMin
+    "min", MathMin,
+    "imul", MathImul
   ));
 }

=======================================
--- /branches/bleeding_edge/src/objects.h       Thu Apr 25 09:00:32 2013
+++ /branches/bleeding_edge/src/objects.h       Fri Apr 26 01:52:35 2013
@@ -5679,7 +5679,8 @@
   V(Math, pow, MathPow)                             \
   V(Math, random, MathRandom)                       \
   V(Math, max, MathMax)                             \
-  V(Math, min, MathMin)
+  V(Math, min, MathMin)                             \
+  V(Math, imul, MathImul)


 enum BuiltinFunctionId {
=======================================
--- /branches/bleeding_edge/src/runtime.cc      Thu Apr 25 05:02:23 2013
+++ /branches/bleeding_edge/src/runtime.cc      Fri Apr 26 01:52:35 2013
@@ -6285,6 +6285,16 @@
   // NumberFromDouble may return a Smi instead of a Number object
   return isolate->heap()->NumberFromDouble(x);
 }
+
+
+RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberImul) {
+  NoHandleAllocation ha(isolate);
+  ASSERT(args.length() == 2);
+
+  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
+  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
+  return isolate->heap()->NumberFromInt32(x * y);
+}


 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringAdd) {
=======================================
--- /branches/bleeding_edge/src/runtime.h       Thu Apr 25 05:02:23 2013
+++ /branches/bleeding_edge/src/runtime.h       Fri Apr 26 01:52:35 2013
@@ -145,6 +145,7 @@
   F(NumberMod, 2, 1) \
   F(NumberUnaryMinus, 1, 1) \
   F(NumberAlloc, 0, 1) \
+  F(NumberImul, 2, 1) \
   \
   F(StringAdd, 2, 1) \
   F(StringBuilderConcat, 3, 1) \

--
--
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