Index: test/mjsunit/keyed-call-ic.js |
=================================================================== |
--- test/mjsunit/keyed-call-ic.js (revision 0) |
+++ test/mjsunit/keyed-call-ic.js (revision 0) |
@@ -0,0 +1,205 @@ |
+// Copyright 2010 the V8 project authors. All rights reserved. |
+// Redistribution and use in source and binary forms, with or without |
+// modification, are permitted provided that the following conditions are |
+// met: |
+// |
+// * Redistributions of source code must retain the above copyright |
+// notice, this list of conditions and the following disclaimer. |
+// * Redistributions in binary form must reproduce the above |
+// copyright notice, this list of conditions and the following |
+// disclaimer in the documentation and/or other materials provided |
+// with the distribution. |
+// * Neither the name of Google Inc. nor the names of its |
+// contributors may be used to endorse or promote products derived |
+// from this software without specific prior written permission. |
+// |
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
+ |
+// A test for keyed call ICs. |
+ |
+var toStringName = 'toString'; |
+var global = this; |
+ |
+function globalFunction1() { |
+ return 'function1'; |
+} |
+ |
+function globalFunction2() { |
+ return 'function2'; |
+} |
+ |
+assertEquals("[object global]", this[toStringName]()); |
+assertEquals("[object global]", global[toStringName]()); |
+ |
+function testGlobals() { |
+ assertEquals("[object global]", this[toStringName]()); |
+ assertEquals("[object global]", global[toStringName]()); |
+} |
+ |
+testGlobals(); |
+ |
+ |
+function F() {} |
+ |
+F.prototype.one = function() {return 'one'; } |
+F.prototype.two = function() {return 'two'; } |
+F.prototype.three = function() {return 'three'; } |
+ |
+var keys = |
+ ['one', 'one', 'one', 'one', 'two', 'two', 'one', 'three', 'one', 'two']; |
+ |
+function testKeyTransitions() { |
+ var i, key, result; |
+ |
+ var f = new F(); |
+ |
+ // Custom call generators |
+ var array = []; |
+ for (i = 0; i != 10; i++) { |
+ key = (i < 8) ? 'push' : 'pop'; |
+ array[key](i); |
+ } |
+ |
+ assertEquals(6, array.length); |
+ for (i = 0; i != array.length; i++) { |
+ assertEquals(i, array[i]); |
+ } |
+ |
+ for (i = 0; i != 10; i++) { |
+ key = (i < 3) ? 'pop' : 'push'; |
+ array[key](i); |
+ } |
+ |
+ assertEquals(10, array.length); |
+ for (i = 0; i != array.length; i++) { |
+ assertEquals(i, array[i]); |
+ } |
+ |
+ var string = 'ABCDEFGHIJ'; |
+ for (i = 0; i != 10; i++) { |
+ key = ((i < 5) ? 'charAt' : 'charCodeAt'); |
+ result = string[key](i); |
+ var message = '\'' + string + '\'[\'' + key + '\'](' + i + ')'; |
+ if (i < 5) { |
+ assertEquals(string.charAt(i), result, message); |
+ } else { |
+ assertEquals(string.charCodeAt(i), result, message); |
+ } |
+ } |
+ |
+ for (i = 0; i != 10; i++) { |
+ key = ((i < 5) ? 'charCodeAt' : 'charAt'); |
+ result = string[key](i); |
+ var message = '\'' + string + '\'[\'' + key + '\'](' + i + ')'; |
+ if (i < 5) { |
+ assertEquals(string.charCodeAt(i), result, message); |
+ } else { |
+ assertEquals(string.charAt(i), result, message); |
+ } |
+ } |
+ |
+ // Function is a constant property |
+ key = 'one'; |
+ for (i = 0; i != 10; i++) { |
+ assertEquals(key, f[key]()); |
+ if (i == 5) { |
+ key = 'two'; // the name change should case a miss |
+ } |
+ } |
+ |
+ // Function is a fast property |
+ f.field = function() { return 'field'; } |
+ key = 'field'; |
+ for (i = 0; i != 10; i++) { |
+ assertEquals(key, f[key]()); |
+ if (i == 5) { |
+ key = 'two'; // the name change should case a miss |
+ } |
+ } |
+ |
+ // Calling on slow case object |
+ f.prop = 0; |
+ delete f.prop; // force the object to the slow case |
+ f.four = function() { return 'four'; } |
+ f.five = function() { return 'five'; } |
+ |
+ key = 'four'; |
+ for (i = 0; i != 10; i++) { |
+ assertEquals(key, f[key]()); |
+ if (i == 5) { |
+ key = 'five'; |
+ } |
+ } |
+ |
+ // Calling on global object |
+ key = 'globalFunction1'; |
+ var expect = 'function1'; |
+ for (i = 0; i != 10; i++) { |
+ assertEquals(expect, global[key]()); |
+ if (i == 5) { |
+ key = 'globalFunction2'; |
+ expect = 'function2'; |
+ } |
+ } |
+} |
+ |
+testKeyTransitions(); |
+ |
+function testTypeTransitions() { |
+ var f = new F(); |
+ var s = ''; |
+ var m = 'one'; |
+ var i; |
+ |
+ s = ''; |
+ for (i = 0; i != 10; i++) { |
+ if (i == 5) { F.prototype.one = function() { return '1'; } } |
+ s += f[m](); |
+ } |
+ assertEquals("oneoneoneoneone11111", s); |
+ |
+ s = ''; |
+ for (i = 0; i != 10; i++) { |
+ if (i == 5) { f.__proto__ = { one: function() { return 'I'; } } } |
+ s += f[m](); |
+ } |
+ assertEquals("11111IIIII", s); |
+ |
+ s = ''; |
+ for (i = 0; i != 10; i++) { |
+ if (i == 5) { f.one = function() { return 'ONE'; } } |
+ s += f[m](); |
+ } |
+ assertEquals("IIIIIONEONEONEONEONE", s); |
+ |
+ m = 'toString'; |
+ |
+ s = ''; |
+ var obj = { toString: function() { return '2'; } }; |
+ for (i = 0; i != 10; i++) { |
+ if (i == 5) { obj = "TWO"; } |
+ s += obj[m](); |
+ } |
+ assertEquals("22222TWOTWOTWOTWOTWO", s); |
+ |
+ s = ''; |
+ obj = { toString: function() { return 'ONE'; } }; |
+ m = 'toString'; |
+ for (i = 0; i != 10; i++) { |
+ if (i == 5) { obj = 1; } |
+ s += obj[m](); |
+ } |
+ assertEquals("ONEONEONEONEONE11111", s); |
+} |
+ |
+testTypeTransitions(); |