1// Copyright 2010 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// A test for keyed call ICs. 29 30var toStringName = 'toString'; 31var global = this; 32 33function globalFunction1() { 34 return 'function1'; 35} 36 37function globalFunction2() { 38 return 'function2'; 39} 40 41assertEquals("[object global]", this[toStringName]()); 42assertEquals("[object global]", global[toStringName]()); 43 44function testGlobals() { 45 assertEquals("[object global]", this[toStringName]()); 46 assertEquals("[object global]", global[toStringName]()); 47} 48 49testGlobals(); 50 51 52function F() {} 53 54F.prototype.one = function() {return 'one'; } 55F.prototype.two = function() {return 'two'; } 56F.prototype.three = function() {return 'three'; } 57 58var keys = 59 ['one', 'one', 'one', 'one', 'two', 'two', 'one', 'three', 'one', 'two']; 60 61function testKeyTransitions() { 62 var i, key, result, message; 63 64 var f = new F(); 65 66 // Custom call generators 67 var array = []; 68 for (i = 0; i != 10; i++) { 69 key = (i < 8) ? 'push' : 'pop'; 70 array[key](i); 71 } 72 73 assertEquals(6, array.length); 74 for (i = 0; i != array.length; i++) { 75 assertEquals(i, array[i]); 76 } 77 78 for (i = 0; i != 10; i++) { 79 key = (i < 3) ? 'pop' : 'push'; 80 array[key](i); 81 } 82 83 assertEquals(10, array.length); 84 for (i = 0; i != array.length; i++) { 85 assertEquals(i, array[i]); 86 } 87 88 var string = 'ABCDEFGHIJ'; 89 for (i = 0; i != 10; i++) { 90 key = ((i < 5) ? 'charAt' : 'charCodeAt'); 91 result = string[key](i); 92 message = '\'' + string + '\'[\'' + key + '\'](' + i + ')'; 93 if (i < 5) { 94 assertEquals(string.charAt(i), result, message); 95 } else { 96 assertEquals(string.charCodeAt(i), result, message); 97 } 98 } 99 100 for (i = 0; i != 10; i++) { 101 key = ((i < 5) ? 'charCodeAt' : 'charAt'); 102 result = string[key](i); 103 message = '\'' + string + '\'[\'' + key + '\'](' + i + ')'; 104 if (i < 5) { 105 assertEquals(string.charCodeAt(i), result, message); 106 } else { 107 assertEquals(string.charAt(i), result, message); 108 } 109 } 110 111 // Function is a constant property 112 key = 'one'; 113 for (i = 0; i != 10; i++) { 114 assertEquals(key, f[key]()); 115 if (i == 5) { 116 key = 'two'; // the name change should case a miss 117 } 118 } 119 120 // Function is a fast property 121 f.field = function() { return 'field'; } 122 key = 'field'; 123 for (i = 0; i != 10; i++) { 124 assertEquals(key, f[key]()); 125 if (i == 5) { 126 key = 'two'; // the name change should case a miss 127 } 128 } 129 130 // Calling on slow case object 131 f.prop = 0; 132 delete f.prop; // force the object to the slow case 133 f.four = function() { return 'four'; } 134 f.five = function() { return 'five'; } 135 136 key = 'four'; 137 for (i = 0; i != 10; i++) { 138 assertEquals(key, f[key]()); 139 if (i == 5) { 140 key = 'five'; 141 } 142 } 143 144 // Calling on global object 145 key = 'globalFunction1'; 146 var expect = 'function1'; 147 for (i = 0; i != 10; i++) { 148 assertEquals(expect, global[key]()); 149 if (i == 5) { 150 key = 'globalFunction2'; 151 expect = 'function2'; 152 } 153 } 154} 155 156testKeyTransitions(); 157 158function testTypeTransitions() { 159 var f = new F(); 160 var s = ''; 161 var m = 'one'; 162 var i; 163 164 s = ''; 165 for (i = 0; i != 10; i++) { 166 if (i == 5) { F.prototype.one = function() { return '1'; } } 167 s += f[m](); 168 } 169 assertEquals("oneoneoneoneone11111", s); 170 171 s = ''; 172 for (i = 0; i != 10; i++) { 173 if (i == 5) { f.__proto__ = { one: function() { return 'I'; } } } 174 s += f[m](); 175 } 176 assertEquals("11111IIIII", s); 177 178 s = ''; 179 for (i = 0; i != 10; i++) { 180 if (i == 5) { f.one = function() { return 'ONE'; } } 181 s += f[m](); 182 } 183 assertEquals("IIIIIONEONEONEONEONE", s); 184 185 m = 'toString'; 186 187 s = ''; 188 var obj = { toString: function() { return '2'; } }; 189 for (i = 0; i != 10; i++) { 190 if (i == 5) { obj = "TWO"; } 191 s += obj[m](); 192 } 193 assertEquals("22222TWOTWOTWOTWOTWO", s); 194 195 s = ''; 196 obj = { toString: function() { return 'ONE'; } }; 197 m = 'toString'; 198 for (i = 0; i != 10; i++) { 199 if (i == 5) { obj = 1; } 200 s += obj[m](); 201 } 202 assertEquals("ONEONEONEONEONE11111", s); 203} 204 205testTypeTransitions(); 206