1// Copyright 2011 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 --smi-only-arrays --expose-gc
29
30// Ensure that ElementsKind transitions in various situations are hoisted (or
31// not hoisted) correctly, don't change the semantics programs and don't trigger
32// deopt through hoisting in important situations.
33
34support_smi_only_arrays = %HasFastSmiOnlyElements(new Array(1,2,3,4,5,6));
35
36if (support_smi_only_arrays) {
37  print("Tests include smi-only arrays.");
38} else {
39  print("Tests do NOT include smi-only arrays.");
40}
41
42// Force existing ICs from previous stress runs to be flushed, otherwise the
43// assumptions in this test about when deoptimizations get triggered are not
44// valid.
45gc();
46
47if (support_smi_only_arrays) {
48  // Make sure that a simple elements array transitions inside a loop before
49  // stores to an array gets hoisted in a way that doesn't generate a deopt in
50  // simple cases.}
51  function testDoubleConversion4(a) {
52    var object = new Object();
53    a[0] = 0;
54    var count = 3;
55    do {
56      a[0] = object;
57    } while (--count > 0);
58  }
59
60  testDoubleConversion4(new Array(5));
61  %OptimizeFunctionOnNextCall(testDoubleConversion4);
62  testDoubleConversion4(new Array(5));
63  testDoubleConversion4(new Array(5));
64  assertTrue(2 != %GetOptimizationStatus(testDoubleConversion4));
65
66  // Make sure that non-element related map checks that are not preceded by
67  // transitions in a loop still get hoisted in a way that doesn't generate a
68  // deopt in simple cases.
69  function testExactMapHoisting(a) {
70    var object = new Object();
71    a.foo = 0;
72    a[0] = 0;
73    a[1] = 1;
74    var count = 3;
75    do {
76      a.foo = object; // This map check should be hoistable
77      a[1] = object;
78      result = a.foo == object && a[1] == object;
79    } while (--count > 0);
80  }
81
82  testExactMapHoisting(new Array(5));
83  %OptimizeFunctionOnNextCall(testExactMapHoisting);
84  testExactMapHoisting(new Array(5));
85  testExactMapHoisting(new Array(5));
86  assertTrue(2 != %GetOptimizationStatus(testExactMapHoisting));
87
88  // Make sure that non-element related map checks do NOT get hoisted if they
89  // depend on an elements transition before them and it's not possible to hoist
90  // that transition.
91  function testExactMapHoisting2(a) {
92    var object = new Object();
93    a.foo = 0;
94    a[0] = 0;
95    a[1] = 1;
96    var count = 3;
97    do {
98      if (a.bar === undefined) {
99        a[1] = 2.5;
100      }
101      a.foo = object; // This map check should NOT be hoistable because it
102                      // includes a check for the FAST_ELEMENTS map as well as
103                      // the FAST_DOUBLE_ELEMENTS map, which depends on the
104                      // double transition above in the if, which cannot be
105                      // hoisted.
106    } while (--count > 0);
107  }
108
109  testExactMapHoisting2(new Array(5));
110  %OptimizeFunctionOnNextCall(testExactMapHoisting2);
111  testExactMapHoisting2(new Array(5));
112  testExactMapHoisting2(new Array(5));
113  assertTrue(2 != %GetOptimizationStatus(testExactMapHoisting2));
114
115  // Make sure that non-element related map checks do get hoisted if they use
116  // the transitioned map for the check and all transitions that they depend
117  // upon can hoisted, too.
118  function testExactMapHoisting3(a) {
119    var object = new Object();
120    a.foo = 0;
121    a[0] = 0;
122    a[1] = 1;
123    var count = 3;
124    do {
125      a[1] = 2.5;
126      a.foo = object; // This map check should be hoistable because all elements
127                      // transitions in the loop can also be hoisted.
128    } while (--count > 0);
129  }
130
131  var add_transition = new Array(5);
132  add_transition.foo = 0;
133  add_transition[0] = new Object(); // For FAST_ELEMENT transition to be created
134  testExactMapHoisting3(new Array(5));
135  %OptimizeFunctionOnNextCall(testExactMapHoisting3);
136  testExactMapHoisting3(new Array(5));
137  testExactMapHoisting3(new Array(5));
138  assertTrue(2 != %GetOptimizationStatus(testExactMapHoisting3));
139
140  function testDominatingTransitionHoisting1(a) {
141    var object = new Object();
142    a[0] = 0;
143    var count = 3;
144    do {
145      if (a.baz != true) {
146        a[1] = 2.5;
147      }
148      a[0] = object;
149    } while (--count > 3);
150  }
151
152  testDominatingTransitionHoisting1(new Array(5));
153  %OptimizeFunctionOnNextCall(testDominatingTransitionHoisting1);
154  testDominatingTransitionHoisting1(new Array(5));
155  testDominatingTransitionHoisting1(new Array(5));
156  assertTrue(2 != %GetOptimizationStatus(testDominatingTransitionHoisting1));
157
158  function testHoistingWithSideEffect(a) {
159    var object = new Object();
160    a[0] = 0;
161    var count = 3;
162    do {
163      assertTrue(true);
164      a[0] = object;
165    } while (--count > 3);
166  }
167
168  testHoistingWithSideEffect(new Array(5));
169  %OptimizeFunctionOnNextCall(testHoistingWithSideEffect);
170  testHoistingWithSideEffect(new Array(5));
171  testHoistingWithSideEffect(new Array(5));
172  assertTrue(2 != %GetOptimizationStatus(testHoistingWithSideEffect));
173
174  function testStraightLineDupeElinination(a,b,c,d,e,f) {
175    var count = 3;
176    do {
177      assertTrue(true);
178      a[0] = b;
179      a[1] = c;
180      a[2] = d;
181      assertTrue(true);
182      a[3] = e; // TransitionElementsKind should be eliminated despite call.
183      a[4] = f;
184    } while (--count > 3);
185  }
186
187  testStraightLineDupeElinination(new Array(0, 0, 0, 0, 0),0,0,0,0,.5);
188  testStraightLineDupeElinination(new Array(0, 0, 0, 0, 0),0,0,0,.5,0);
189  testStraightLineDupeElinination(new Array(0, 0, 0, 0, 0),0,0,.5,0,0);
190  testStraightLineDupeElinination(new Array(0, 0, 0, 0, 0),0,.5,0,0,0);
191  testStraightLineDupeElinination(new Array(0, 0, 0, 0, 0),.5,0,0,0,0);
192  testStraightLineDupeElinination(new Array(.1,.1,.1,.1,.1),0,0,0,0,.5);
193  testStraightLineDupeElinination(new Array(.1,.1,.1,.1,.1),0,0,0,.5,0);
194  testStraightLineDupeElinination(new Array(.1,.1,.1,.1,.1),0,0,.5,0,0);
195  testStraightLineDupeElinination(new Array(.1,.1,.1,.1,.1),0,.5,0,0,0);
196  testStraightLineDupeElinination(new Array(.1,.1,.1,.1,.1),.5,0,0,0,0);
197  testStraightLineDupeElinination(new Array(5),.5,0,0,0,0);
198  testStraightLineDupeElinination(new Array(5),0,.5,0,0,0);
199  testStraightLineDupeElinination(new Array(5),0,0,.5,0,0);
200  testStraightLineDupeElinination(new Array(5),0,0,0,.5,0);
201  testStraightLineDupeElinination(new Array(5),0,0,0,0,.5);
202  testStraightLineDupeElinination(new Array(5),.5,0,0,0,0);
203  testStraightLineDupeElinination(new Array(5),0,.5,0,0,0);
204  testStraightLineDupeElinination(new Array(5),0,0,.5,0,0);
205  testStraightLineDupeElinination(new Array(5),0,0,0,.5,0);
206  testStraightLineDupeElinination(new Array(5),0,0,0,0,.5);
207  %OptimizeFunctionOnNextCall(testStraightLineDupeElinination);
208  testStraightLineDupeElinination(new Array(5));
209  testStraightLineDupeElinination(new Array(5));
210  assertTrue(2 != %GetOptimizationStatus(testStraightLineDupeElinination));
211}
212