1// Copyright 2012 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6//     * Redistributions of source code must retain the above copyright
7//       notice, this list of conditions and the following disclaimer.
8//     * Redistributions in binary form must reproduce the above
9//       copyright notice, this list of conditions and the following
10//       disclaimer in the documentation and/or other materials provided
11//       with the distribution.
12//     * Neither the name of Google Inc. nor the names of its
13//       contributors may be used to endorse or promote products derived
14//       from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28// Flags: --allow-natives-syntax --expose-gc
29
30// Test uint32 handing in optimized frames.
31
32var K1 = 0x7fffffff;
33var K2 = 0xffffffff;
34
35var uint32_array = new Uint32Array(2);
36uint32_array[0] = K1;
37uint32_array[1] = K2;
38
39function ChangeI2T(arr, i) {
40  return uint32_array[i];
41}
42
43assertEquals(K1, ChangeI2T(uint32_array, 0));
44assertEquals(K2, ChangeI2T(uint32_array, 1));
45%OptimizeFunctionOnNextCall(ChangeI2T);
46assertEquals(K1, ChangeI2T(uint32_array, 0));
47// Loop to force inline allocation failure and a call into runtime.
48for (var i = 0; i < 80000; i++) {
49  assertEquals(K2, ChangeI2T(uint32_array, 1));
50}
51
52function SideEffect() {
53  with ({}) { }  // not inlinable
54}
55
56function Deopt(obj, arr, i) {
57  var x = arr[i];
58  SideEffect();  // x will be used by HSimulate.
59  obj.x;
60  return x;
61}
62
63assertEquals(K1, Deopt({x: 0}, uint32_array, 0));
64assertEquals(K2, Deopt({x: 0}, uint32_array, 1));
65%OptimizeFunctionOnNextCall(Deopt);
66assertEquals(K2, Deopt({}, uint32_array, 1));
67
68function ChangeI2D(arr) {
69  // This addition will have a double type feedback so ChangeI2D will
70  // be generated for its operands.
71  return arr[0] + arr[1];
72}
73
74assertEquals(K1 + K2, ChangeI2D(uint32_array));
75assertEquals(K1 + K2, ChangeI2D(uint32_array));
76%OptimizeFunctionOnNextCall(ChangeI2D);
77assertEquals(K1 + K2, ChangeI2D(uint32_array));
78
79function ShrShr(val) {
80  return (val >>> 0) >>> 1;
81}
82
83assertEquals(K1, ShrShr(K2 | 0));
84assertEquals(K1, ShrShr(K2 | 0));
85%OptimizeFunctionOnNextCall(ShrShr);
86assertEquals(K1, ShrShr(K2 | 0));
87
88function SarShr(val) {
89  return val >> (-2 >>> 0);
90}
91
92var K3 = 0x80000000;
93assertEquals(-2, SarShr(K3 | 0));
94assertEquals(-2, SarShr(K3 | 0));
95%OptimizeFunctionOnNextCall(SarShr);
96assertEquals(-2, SarShr(K3 | 0));
97
98function Uint32Phi(a, b, c) {
99  var i = a ? (b >>> 0) : (c >>> 0);
100  return (i | 0);
101}
102
103var K4 = 0x80000001;
104assertEquals(K3 | 0, Uint32Phi(true, K3, K4));
105assertEquals(K4 | 0, Uint32Phi(false, K3, K4));
106assertEquals(K3 | 0, Uint32Phi(true, K3, K4));
107assertEquals(K4 | 0, Uint32Phi(false, K3, K4));
108%OptimizeFunctionOnNextCall(Uint32Phi);
109assertEquals(K3 | 0, Uint32Phi(true, K3, K4));
110assertEquals(K4 | 0, Uint32Phi(false, K3, K4));
111
112function NonUint32Phi(a, b, c) {
113  var i = a ? (b >>> 0) : c;
114  return (i | 0);
115}
116
117assertEquals(K3 | 0, NonUint32Phi(true, K3, K4));
118assertEquals(K4 | 0, NonUint32Phi(false, K3, K4));
119assertEquals(K3 | 0, NonUint32Phi(true, K3, K4));
120assertEquals(K4 | 0, NonUint32Phi(false, K3, K4));
121%OptimizeFunctionOnNextCall(NonUint32Phi);
122assertEquals(K3 | 0, NonUint32Phi(true, K3, K4));
123assertEquals(K4 | 0, NonUint32Phi(false, K3, K4));
124
125function PhiOfPhi(x) {
126  var a = (x >>> 0);
127  for (var i = 0; i < 2; i++) {
128    for (var j = 0; j < 2; j++) {
129      a = (a >>> 0);
130    }
131  }
132  return (a | 0);
133}
134
135assertEquals(1, PhiOfPhi(1));
136assertEquals(1, PhiOfPhi(1));
137%OptimizeFunctionOnNextCall(PhiOfPhi);
138assertEquals(K3 | 0, PhiOfPhi(K3));
139
140function PhiOfPhiUnsafe(x) {
141  var a = x >>> 0;
142  for (var i = 0; i < 2; i++) {
143    for (var j = 0; j < 2; j++) {
144      a = (a >>> 0);
145    }
146  }
147  return a + a;
148}
149
150assertEquals(2, PhiOfPhiUnsafe(1));
151assertEquals(2, PhiOfPhiUnsafe(1));
152%OptimizeFunctionOnNextCall(PhiOfPhiUnsafe);
153assertEquals(2 * K3, PhiOfPhiUnsafe(K3));
154
155var old_array = new Array(1000);
156
157for (var i = 0; i < old_array.length; i++) old_array[i] = null;
158
159// Force promotion.
160gc();
161gc();
162
163function FillOldArrayWithHeapNumbers(N) {
164  for (var i = 0; i < N; i++) {
165    old_array[i] = uint32_array[1];
166  }
167}
168
169FillOldArrayWithHeapNumbers(1);
170FillOldArrayWithHeapNumbers(1);
171%OptimizeFunctionOnNextCall(FillOldArrayWithHeapNumbers);
172FillOldArrayWithHeapNumbers(old_array.length);
173gc();
174
175// Test that HArgumentsObject does not prevent uint32 optimization and
176// that arguments object with uint32 values inside is correctly materialized.
177function Pack(x, y) {
178  try {  // Prevent inlining.
179    return [x, y];
180  } catch (e) {
181  }
182}
183
184function InnerWithArguments(x, f) {
185  "use strict";
186  x >>>= 8;
187  return f(arguments[0], x|0);
188}
189
190function Outer(v, f) {
191  return InnerWithArguments(v >>> 0, f);
192}
193
194assertArrayEquals([0x0100, 0x01], Outer(0x0100, Pack));
195assertArrayEquals([0x0100, 0x01], Outer(0x0100, Pack));
196assertArrayEquals([0x0100, 0x01], Outer(0x0100, Pack));
197%OptimizeFunctionOnNextCall(Outer);
198assertArrayEquals([0x0100, 0x01], Outer(0x0100, Pack));
199assertArrayEquals([0xFFFFFFFF, 0x00FFFFFF], Outer(-1, Pack));
200
201// Cause deopt inside InnerWithArguments by passing different pack function.
202assertArrayEquals([0xFFFFFFFF, 0x00FFFFFF], Outer(-1, function (x, y) {
203  return [x, y];
204}));
205