1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2011 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Redistribution and use in source and binary forms, with or without
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// modification, are permitted provided that the following conditions are
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// met:
5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//     * Redistributions of source code must retain the above copyright
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//       notice, this list of conditions and the following disclaimer.
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//     * Redistributions in binary form must reproduce the above
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//       copyright notice, this list of conditions and the following
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//       disclaimer in the documentation and/or other materials provided
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//       with the distribution.
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//     * Neither the name of Google Inc. nor the names of its
13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//       contributors may be used to endorse or promote products derived
14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//       from this software without specific prior written permission.
15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//
16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Flags: --allow-natives-syntax --max-opt-count=100 --noalways-opt
29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// We specify max-opt-count because we opt/deopt the same function many
31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// times.
32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// It's nice to run this in other browsers too.
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvar standalone = false;
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochif (standalone) {
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  assertTrue = function(val) {
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (val != true) {
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      print("FAILURE");
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  assertFalse = function(val) {
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (val != false) {
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      print("FAILURE");
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  assertEquals = function(expected, val) {
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (expected !== val) {
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      print("FAILURE");
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  empty_func = function(name) { }
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  assertUnoptimized = empty_func;
56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  assertOptimized = empty_func;
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  optimize = empty_func;
59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  clearFunctionTypeFeedback = empty_func;
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  deoptimizeFunction = empty_func;
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} else {
62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  optimize = function(name) {
63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    %OptimizeFunctionOnNextCall(name);
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  clearFunctionTypeFeedback = function(name) {
66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    %ClearFunctionTypeFeedback(name);
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  deoptimizeFunction = function(name) {
69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    %DeoptimizeFunction(name);
70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction base_setter_test(create_func, index, store_value) {
74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  var calls = 0;
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Testcase: setter in prototype chain
77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  foo = function(a) { a[index] = store_value; }
78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  var a = create_func();
79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  var ap = [];
80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ap.__defineSetter__(index, function() { calls++; });
81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  foo(a);
83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  foo(a);
84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  foo(a);
85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  delete a[index];
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  assertEquals(0, calls);
88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  a.__proto__ = ap;
89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  foo(a);
90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  assertEquals(1, calls);
91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  optimize(foo);
92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  foo(a);
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  assertEquals(2, calls);
94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  assertOptimized(foo);
95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Testcase: setter added on prototype chain object already in place.
97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  clearFunctionTypeFeedback(foo);
98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  deoptimizeFunction(foo);
99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  clearFunctionTypeFeedback(foo);
100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  calls = 0;
101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  a = create_func();
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  var apap = [];
103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  a.__proto__ = apap;
104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  foo(a);
105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  foo(a);
106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  foo(a);
107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  delete a[index];
108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  apap.__defineSetter__(index, function() { calls++; });
109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  foo(a);
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  foo(a);
111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  foo(a);
112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  assertEquals(3, calls);
113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Testcase: setter "deep" in prototype chain.
115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  clearFunctionTypeFeedback(foo);
116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  deoptimizeFunction(foo);
117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  clearFunctionTypeFeedback(foo);
118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  calls = 0;
119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  a = create_func();
121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  var ap2 = [];
122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  a.__proto__ = ap2;
123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  foo(a);
124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  foo(a);
125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  foo(a);
126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  delete a[index];
127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  assertEquals(0, calls);
129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ap2.__proto__ = ap;  // "sneak" in a callback.
131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The sneak case should be caught by unoptimized code too.
132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  assertUnoptimized(foo);
133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  foo(a);
134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  foo(a);
135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  foo(a);
136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  assertEquals(3, calls);
137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Testcase: setter added after optimization (feedback is monomorphic)
139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  clearFunctionTypeFeedback(foo);
140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  deoptimizeFunction(foo);
141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  clearFunctionTypeFeedback(foo);
142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  calls = 0;
143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  a = create_func();
145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ap2 = [];
146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  a.__proto__ = ap2;
147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  foo(a);
148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  foo(a);
149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  foo(a);
150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  optimize(foo);
151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  foo(a);
152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  assertOptimized(foo);
153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  delete a[index];
154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ap2.__proto__ = ap;
155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  foo(a);
156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  assertUnoptimized(foo);  // map shape change should deopt foo.
157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  assertEquals(1, calls);
158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Testcase: adding additional setters to a prototype chain that already has
160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // one shouldn't deopt anything. (ie, we aren't changing the map shape).
161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  clearFunctionTypeFeedback(foo);
162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  calls = 0;
163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  a = create_func();
165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  a.__proto__ = ap2;
166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bar = function(a) { a[index+1] = store_value; }
167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bar(a);
168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bar(a);
169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bar(a);  // store should be generic
170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  optimize(bar);
171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bar(a);
172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  assertOptimized(bar);
173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  assertEquals(0, calls);
174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  delete a[index+1];
175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ap2.__defineSetter__(index+1, function() { calls++; });
176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bar(a);
177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  assertOptimized(bar);
178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  assertEquals(1, calls);
179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Verify that map transitions don't confuse us.
182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochcreate_func_smi = function() { return [,,,,,,5]; }
183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochcreate_func_double = function() { return [0,,3.2,,,,5.5]; }
184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochcreate_func_fast = function() { return [,,,,,,true]; }
185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochcreate_func_dictionary = function() { var a = []; a.length = 100000; return a; }
186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvar cf = [create_func_smi,
188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          create_func_double,
189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          create_func_fast,
190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          create_func_dictionary];
191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvar values = [3, 3.5, true];
193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfor(var c = 0; c < 3; c++) {
195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for(var s = 0; s < 3; s++) {
196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    base_setter_test(cf[c], 0, values[s]);
197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    base_setter_test(cf[c], 1, values[s]);
198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
200