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