1// Copyright 2012 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// Flags: --allow-natives-syntax --expose-gc
29// Flags: --noalways-opt
30
31var elements_kind = {
32  fast_smi_only            :  'fast smi only elements',
33  fast                     :  'fast elements',
34  fast_double              :  'fast double elements',
35  dictionary               :  'dictionary elements',
36  external_byte            :  'external byte elements',
37  external_unsigned_byte   :  'external unsigned byte elements',
38  external_short           :  'external short elements',
39  external_unsigned_short  :  'external unsigned short elements',
40  external_int             :  'external int elements',
41  external_unsigned_int    :  'external unsigned int elements',
42  external_float           :  'external float elements',
43  external_double          :  'external double elements',
44  external_pixel           :  'external pixel elements'
45}
46
47function getKind(obj) {
48  if (%HasFastSmiElements(obj)) return elements_kind.fast_smi_only;
49  if (%HasFastObjectElements(obj)) return elements_kind.fast;
50  if (%HasFastDoubleElements(obj)) return elements_kind.fast_double;
51  if (%HasDictionaryElements(obj)) return elements_kind.dictionary;
52}
53
54function isHoley(obj) {
55  if (%HasFastHoleyElements(obj)) return true;
56  return false;
57}
58
59function assertKind(expected, obj, name_opt) {
60  assertEquals(expected, getKind(obj), name_opt);
61}
62
63// Verify that basic elements kind feedback works for non-constructor
64// array calls (as long as the call is made through an IC, and not
65// a CallStub).
66(function (){
67  function create0() {
68    return Array();
69  }
70
71  // Calls through ICs need warm up through uninitialized, then
72  // premonomorphic first.
73  create0();
74  a = create0();
75  assertKind(elements_kind.fast_smi_only, a);
76  a[0] = 3.5;
77  b = create0();
78  assertKind(elements_kind.fast_double, b);
79
80  function create1(arg) {
81    return Array(arg);
82  }
83
84  create1(0);
85  create1(0);
86  a = create1(0);
87  assertFalse(isHoley(a));
88  assertKind(elements_kind.fast_smi_only, a);
89  a[0] = "hello";
90  b = create1(10);
91  assertTrue(isHoley(b));
92  assertKind(elements_kind.fast, b);
93
94  a = create1(100000);
95  assertKind(elements_kind.fast_smi_only, a);
96
97  function create3(arg1, arg2, arg3) {
98    return Array(arg1, arg2, arg3);
99  }
100
101  create3(1,2,3);
102  create3(1,2,3);
103  a = create3(1,2,3);
104  a[0] = 3.035;
105  assertKind(elements_kind.fast_double, a);
106  b = create3(1,2,3);
107  assertKind(elements_kind.fast_double, b);
108  assertFalse(isHoley(b));
109})();
110
111
112// Verify that keyed calls work
113(function (){
114  function create0(name) {
115    return this[name]();
116  }
117
118  name = "Array";
119  create0(name);
120  create0(name);
121  a = create0(name);
122  a[0] = 3.5;
123  b = create0(name);
124  assertKind(elements_kind.fast_double, b);
125})();
126
127
128// Verify that feedback is turned off if the call site goes megamorphic.
129(function (){
130  function foo(arg) { return arg(); }
131  foo(Array);
132  foo(function() {});
133  foo(Array);
134
135  gc();
136
137  a = foo(Array);
138  a[0] = 3.5;
139  b = foo(Array);
140  // b doesn't benefit from elements kind feedback at a megamorphic site.
141  assertKind(elements_kind.fast_smi_only, b);
142})();
143
144
145// Verify that crankshaft consumes type feedback.
146(function (){
147  function create0() {
148    return Array();
149  }
150
151  create0();
152  create0();
153  a = create0();
154  a[0] = 3.5;
155    %OptimizeFunctionOnNextCall(create0);
156  create0();
157  create0();
158  b = create0();
159  assertKind(elements_kind.fast_double, b);
160  assertOptimized(create0);
161
162  function create1(arg) {
163    return Array(arg);
164  }
165
166  create1(8);
167  create1(8);
168  a = create1(8);
169  a[0] = 3.5;
170    %OptimizeFunctionOnNextCall(create1);
171  b = create1(8);
172  assertKind(elements_kind.fast_double, b);
173  assertOptimized(create1);
174
175  function createN(arg1, arg2, arg3) {
176    return Array(arg1, arg2, arg3);
177  }
178
179  createN(1, 2, 3);
180  createN(1, 2, 3);
181  a = createN(1, 2, 3);
182  a[0] = 3.5;
183    %OptimizeFunctionOnNextCall(createN);
184  b = createN(1, 2, 3);
185  assertKind(elements_kind.fast_double, b);
186  assertOptimized(createN);
187})();
188
189// Verify that cross context calls work
190(function (){
191  var realmA = Realm.current();
192  var realmB = Realm.create();
193  assertEquals(0, realmA);
194  assertEquals(1, realmB);
195
196  function instanceof_check(type) {
197    assertTrue(type() instanceof type);
198    assertTrue(type(5) instanceof type);
199    assertTrue(type(1,2,3) instanceof type);
200  }
201
202  var realmBArray = Realm.eval(realmB, "Array");
203  instanceof_check(Array);
204  instanceof_check(Array);
205  instanceof_check(Array);
206  instanceof_check(realmBArray);
207  instanceof_check(realmBArray);
208  instanceof_check(realmBArray);
209})();
210