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
30// Limit the number of stress runs to reduce polymorphism it defeats some of the
31// assumptions made about how elements transitions work because transition stubs
32// end up going generic.
33// Flags: --stress-runs=2
34
35var elements_kind = {
36  fast_smi_only            :  'fast smi only elements',
37  fast                     :  'fast elements',
38  fast_double              :  'fast double elements',
39  dictionary               :  'dictionary elements',
40  external_byte            :  'external byte elements',
41  external_unsigned_byte   :  'external unsigned byte elements',
42  external_short           :  'external short elements',
43  external_unsigned_short  :  'external unsigned short elements',
44  external_int             :  'external int elements',
45  external_unsigned_int    :  'external unsigned int elements',
46  external_float           :  'external float elements',
47  external_double          :  'external double elements',
48  external_pixel           :  'external pixel elements'
49}
50
51function getKind(obj) {
52  if (%HasFastSmiElements(obj)) return elements_kind.fast_smi_only;
53  if (%HasFastObjectElements(obj)) return elements_kind.fast;
54  if (%HasFastDoubleElements(obj)) return elements_kind.fast_double;
55  if (%HasDictionaryElements(obj)) return elements_kind.dictionary;
56  // Every external kind is also an external array.
57  assertTrue(%HasExternalArrayElements(obj));
58  if (%HasExternalByteElements(obj)) {
59    return elements_kind.external_byte;
60  }
61  if (%HasExternalUnsignedByteElements(obj)) {
62    return elements_kind.external_unsigned_byte;
63  }
64  if (%HasExternalShortElements(obj)) {
65    return elements_kind.external_short;
66  }
67  if (%HasExternalUnsignedShortElements(obj)) {
68    return elements_kind.external_unsigned_short;
69  }
70  if (%HasExternalIntElements(obj)) {
71    return elements_kind.external_int;
72  }
73  if (%HasExternalUnsignedIntElements(obj)) {
74    return elements_kind.external_unsigned_int;
75  }
76  if (%HasExternalFloatElements(obj)) {
77    return elements_kind.external_float;
78  }
79  if (%HasExternalDoubleElements(obj)) {
80    return elements_kind.external_double;
81  }
82  if (%HasExternalPixelElements(obj)) {
83    return elements_kind.external_pixel;
84  }
85}
86
87function assertKind(expected, obj, name_opt) {
88  assertEquals(expected, getKind(obj), name_opt);
89}
90
91// long-running loop forces OSR.
92%NeverOptimizeFunction(construct_smis);
93%NeverOptimizeFunction(construct_doubles);
94%NeverOptimizeFunction(convert_mixed);
95for (var i = 0; i < 1000000; i++) { }
96
97// This code exists to eliminate the learning influence of AllocationSites
98// on the following tests.
99var __sequence = 0;
100function make_array_string() {
101  this.__sequence = this.__sequence + 1;
102  return "/* " + this.__sequence + " */  [0, 0, 0];"
103}
104function make_array() {
105  return eval(make_array_string());
106}
107
108function construct_smis() {
109  var a = make_array();
110  a[0] = 0;  // Send the COW array map to the steak house.
111  assertKind(elements_kind.fast_smi_only, a);
112  return a;
113}
114function construct_doubles() {
115  var a = construct_smis();
116  a[0] = 1.5;
117  assertKind(elements_kind.fast_double, a);
118  return a;
119}
120
121// Test transition chain SMI->DOUBLE->FAST (crankshafted function will
122// transition to FAST directly).
123function convert_mixed(array, value, kind) {
124  array[1] = value;
125  assertKind(kind, array);
126  assertEquals(value, array[1]);
127}
128smis = construct_smis();
129convert_mixed(smis, 1.5, elements_kind.fast_double);
130
131doubles = construct_doubles();
132convert_mixed(doubles, "three", elements_kind.fast);
133
134convert_mixed(construct_smis(), "three", elements_kind.fast);
135convert_mixed(construct_doubles(), "three", elements_kind.fast);
136
137smis = construct_smis();
138doubles = construct_doubles();
139convert_mixed(smis, 1, elements_kind.fast);
140convert_mixed(doubles, 1, elements_kind.fast);
141assertTrue(%HaveSameMap(smis, doubles));
142
143// Throw away type information in the ICs for next stress run.
144gc();
145