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.