1ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org// Copyright 2013 the V8 project authors. All rights reserved.
2ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org// Redistribution and use in source and binary forms, with or without
3ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org// modification, are permitted provided that the following conditions are
4ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org// met:
5ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org//
6ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org//     * Redistributions of source code must retain the above copyright
7ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org//       notice, this list of conditions and the following disclaimer.
8ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org//     * Redistributions in binary form must reproduce the above
9ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org//       copyright notice, this list of conditions and the following
10ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org//       disclaimer in the documentation and/or other materials provided
11ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org//       with the distribution.
12ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org//     * Neither the name of Google Inc. nor the names of its
13ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org//       contributors may be used to endorse or promote products derived
14ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org//       from this software without specific prior written permission.
15ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org//
16ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
28ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org// Flags: --allow-natives-syntax --max-opt-count=1000
29ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
30ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgvar imul_func = Math.imul;
31ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgfunction imul_polyfill(a, b) {
32ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  var ah  = (a >>> 16) & 0xffff;
33ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  var al = a & 0xffff;
34ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  var bh  = (b >>> 16) & 0xffff;
35ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  var bl = b & 0xffff;
36ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  return ((al * bl) + (((ah * bl + al * bh) << 16) >>> 0) | 0);
37ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org}
38ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
39ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgfunction TestMathImul(expected, a, b) {
40ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  function imul_meth_closure(a, b) { return Math.imul(a, b); }
41ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  function imul_func_closure(a, b) { return imul_func(a, b); }
42ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
43ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // Test reference implementation.
44ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  assertEquals(expected, imul_polyfill(a, b));
45ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
46ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // Test direct method call.
47ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  assertEquals(expected, Math.imul(a, b));
48ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
49ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // Test direct function call.
50ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  assertEquals(expected, imul_func(a, b));
51ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
52ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // Test optimized method call inside closure.
53ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  assertEquals(expected, imul_meth_closure(a, b));
54ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  assertEquals(expected, imul_meth_closure(a, b));
55ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  %OptimizeFunctionOnNextCall(imul_meth_closure);
56ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  assertEquals(expected, imul_meth_closure(a, b));
57ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
58ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // Test optimized function call inside closure.
59ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  assertEquals(expected, imul_func_closure(a, b));
60ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  assertEquals(expected, imul_func_closure(a, b));
61ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  %OptimizeFunctionOnNextCall(imul_func_closure);
62ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  assertEquals(expected, imul_func_closure(a, b));
63ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
64ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // Deoptimize closures and forget type feedback.
65ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  %DeoptimizeFunction(imul_meth_closure);
66ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  %DeoptimizeFunction(imul_func_closure);
67ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  %ClearFunctionTypeFeedback(imul_meth_closure);
68ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  %ClearFunctionTypeFeedback(imul_func_closure);
69ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org}
70ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
71ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(8, 2, 4);
72ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(-8, -1, 8);
73ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(4, -2, -2);
74ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(-5, 0xffffffff, 5);
75ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(-10, 0xfffffffe, 5);
76ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
77ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(0, false, 7);
78ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(0, 7, false);
79ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(0, false, false);
80ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
81ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(7, true, 7);
82ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(7, 7, true);
83ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(1, true, true);
84ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
85ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(0, false, true);
86ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(0, true, false);
87ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
88ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(0, undefined, 7);
89ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(0, 7, undefined);
90ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(0, undefined, undefined);
91ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
92ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(0, -0, 7);
93ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(0, 7, -0);
94ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
95ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(0, 0.1, 7);
96ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(0, 7, 0.1);
97ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(0, 0.9, 7);
98ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(0, 7, 0.9);
99ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(7, 1.1, 7);
100ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(7, 7, 1.1);
101ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(7, 1.9, 7);
102ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(7, 7, 1.9);
103ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
104ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(0, "str", 7);
105ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(0, 7, "str");
106ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
107ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(0, {}, 7);
108ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(0, 7, {});
109ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
110ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(0, [], 7);
111ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(0, 7, []);
112ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
113ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org// 2^30 is a smi boundary on arm and ia32.
114ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgvar two_30 = 1 << 30;
115ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
116ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(-two_30, two_30, 7);
117ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(-two_30, 7, two_30);
118ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(0, two_30, two_30);
119ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
120ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(two_30, -two_30, 7);
121ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(two_30, 7, -two_30);
122ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(0, -two_30, -two_30);
123ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
124ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org// 2^31 is a smi boundary on x64.
125ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgvar two_31 = 2 * two_30;
126ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
127ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(-two_31, two_31, 7);
128ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(-two_31, 7, two_31);
129ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(0, two_31, two_31);
130ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
131ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(-two_31, -two_31, 7);
132ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(-two_31, 7, -two_31);
133ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(0, -two_31, -two_31);
134ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
135ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org// 2^31 - 1 is the largest int32 value.
136ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgvar max_val = two_31 - 1;
137ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
138ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(two_31 - 7, max_val, 7);
139ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(two_31 - 7, 7, max_val);
140ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(1, max_val, max_val);
141ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
142ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org// 2^16 is a boundary value that overflows when squared.
143ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgvar two_16 = 1 << 16;
144ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
145ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(0, two_16, two_16);
146ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(-two_16, two_16 - 1, two_16);
147ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(-two_16, two_16, two_16 - 1);
148ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgTestMathImul(-2 * two_16 + 1, two_16 - 1, two_16 - 1);
149