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
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.
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.
28 // Flags: --allow-natives-syntax --max-opt-count=100 --noalways-opt
29 // Flags: --nocollect-maps
31 // We specify max-opt-count because we opt/deopt the same function many
34 // We specify nocollect-maps because in gcstress we can end up deoptimizing
35 // a function in a gc in the stack guard at the beginning of the (optimized)
36 // function due to leftover map clearing work that results in deoptimizing
37 // dependent code from those maps. The choice is to insert strategic gc()
38 // calls or specify this flag.
40 // It's nice to run this in other browsers too.
41 var standalone = false;
43 assertTrue = function(val) {
49 assertFalse = function(val) {
55 assertEquals = function(expected, val) {
56 if (expected !== val) {
61 empty_func = function(name) { }
62 assertUnoptimized = empty_func;
63 assertOptimized = empty_func;
65 optimize = empty_func;
66 clearFunctionTypeFeedback = empty_func;
67 deoptimizeFunction = empty_func;
69 optimize = function(name) {
70 %OptimizeFunctionOnNextCall(name);
72 clearFunctionTypeFeedback = function(name) {
73 %ClearFunctionTypeFeedback(name);
75 deoptimizeFunction = function(name) {
76 %DeoptimizeFunction(name);
80 function base_getter_test(create_func) {
83 // Testcase: setter in prototype chain
84 foo = function(a) { var x = a[0]; return x + 3; }
85 var a = create_func();
87 ap.__defineGetter__(0, function() { calls++; return 0; });
94 assertEquals(0, calls);
97 assertEquals(1, calls);
100 assertEquals(2, calls);
101 assertOptimized(foo);
103 // Testcase: getter "deep" in prototype chain.
104 clearFunctionTypeFeedback(foo);
105 deoptimizeFunction(foo);
106 clearFunctionTypeFeedback(foo);
117 assertEquals(0, calls);
119 ap2.__proto__ = ap; // "sneak" in a callback.
120 // The sneak case should be caught by unoptimized code too.
121 assertUnoptimized(foo);
125 assertEquals(3, calls);
127 // Testcase: getter added after optimization (feedback is monomorphic)
128 clearFunctionTypeFeedback(foo);
129 deoptimizeFunction(foo);
130 clearFunctionTypeFeedback(foo);
141 assertOptimized(foo);
145 assertOptimized(foo); // getters don't require deopt on shape change.
146 assertEquals(1, calls);
148 // Testcase: adding additional getters to a prototype chain that already has
149 // one shouldn't deopt anything.
150 clearFunctionTypeFeedback(foo);
155 bar = function(a) { return a[3] + 600; }
161 assertOptimized(bar);
162 assertEquals(0, calls);
164 ap2.__defineGetter__(3, function() { calls++; return 0; });
166 assertOptimized(bar);
167 assertEquals(1, calls);
170 // Verify that map transitions don't confuse us.
171 create_func_smi = function() { return [,,,,,,5]; }
172 create_func_double = function() { return [,,,,,,5.5]; }
173 create_func_fast = function() { return [,,,,,,true]; }
175 var cf = [create_func_smi,
179 for(var c = 0; c < cf.length; c++) {
180 base_getter_test(cf[c]);
183 // A special test for LoadKeyedHoleMode. Ensure that optimized is generated
184 // which sets ALLOW_RETURN_HOLE, then add a setter on the prototype that should
185 // cause the function to deoptimize.
188 fun = function(a) { return a[0] + 5.5; }
191 fun(a); // should have a monomorphic KeyedLoadIC.
194 assertOptimized(fun);
196 // returning undefined shouldn't phase us.
199 assertOptimized(fun);
201 // but messing up the prototype chain will.
204 assertUnoptimized(fun);
206 // Construct a non-trivial prototype chain.
207 var a = [3.5,,,,3.5];
209 ap.__proto__ = a.__proto__;
214 assertOptimized(fun);
218 ap.__defineGetter__(0, function() { calls++; return 0; });
220 assertEquals(1, calls);
221 assertUnoptimized(fun);