1 // Copyright 2013 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
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.
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.
28 // Flags: --track-fields --track-double-fields --allow-natives-syntax
30 // Test transitions caused by changes to field representations.
32 function create_smi_object() {
40 var o1 = create_smi_object();
41 var o2 = create_smi_object();
43 // o1,o2 are smi, smi, smi
44 assertTrue(%HaveSameMap(o1, o2));
46 // o1 is smi, double, smi
47 assertFalse(%HaveSameMap(o1, o2));
49 // o2 is smi, double, smi
50 assertTrue(%HaveSameMap(o1, o2));
52 // o3 is initialized as smi, double, smi
53 var o3 = create_smi_object();
54 assertTrue(%HaveSameMap(o1, o3));
56 function set_large(o, v) {
57 o.x01 = v; o.x02 = v; o.x03 = v; o.x04 = v; o.x05 = v; o.x06 = v; o.x07 = v;
58 o.x08 = v; o.x09 = v; o.x10 = v; o.x11 = v; o.x12 = v; o.x13 = v; o.x14 = v;
59 o.x15 = v; o.x16 = v; o.x17 = v; o.x18 = v; o.x19 = v; o.x20 = v; o.x21 = v;
60 o.x22 = v; o.x23 = v; o.x24 = v; o.x25 = v; o.x26 = v; o.x27 = v; o.x28 = v;
61 o.x29 = v; o.x30 = v; o.x31 = v; o.x32 = v; o.x33 = v; o.x34 = v; o.x35 = v;
62 o.x36 = v; o.x37 = v; o.x38 = v; o.x39 = v; o.x40 = v; o.x41 = v; o.x42 = v;
63 o.y01 = v; o.y02 = v; o.y03 = v; o.y04 = v; o.y05 = v; o.y06 = v; o.y07 = v;
64 o.y08 = v; o.y09 = v; o.y10 = v; o.y11 = v; o.y12 = v; o.y13 = v; o.y14 = v;
65 o.y15 = v; o.y16 = v; o.y17 = v; o.y18 = v; o.y19 = v; o.y20 = v; o.y21 = v;
68 // Check that large object migrations work.
72 assertTrue(%HasFastProperties(o4));
75 // o5 is immediately allocated with doubles.
78 assertTrue(%HaveSameMap(o4, o5));
80 function create_smi_object2() {
89 var o6 = create_smi_object2();
90 var o7 = create_smi_object2();
92 assertTrue(%HaveSameMap(o6, o7));
95 assertFalse(%HaveSameMap(o6, o7));
96 // Smi, double, object.
98 assertFalse(%HaveSameMap(o6, o7));
99 // Smi, double, object.
101 assertTrue(%HaveSameMap(o6, o7));
103 function poly_load(o, b) {
116 poly_load(of1, false);
117 poly_load(of1, false);
118 poly_load(of2, true);
119 %OptimizeFunctionOnNextCall(poly_load);
120 assertEquals("[object Object]10", poly_load(of1, true));
122 // Ensure small object literals with doubles do not share double storage.
123 function object_literal() { return {"a":1.5}; }
124 var o8 = object_literal();
125 var o9 = object_literal();
127 assertEquals(1.5, o9.a);
129 // Ensure double storage is not leaked in the case of polymorphic loads.
130 function load_poly(o) {
134 var o10 = { "a": 1.6 };
135 var o11 = { "b": 1, "a": 1.7 };
139 %OptimizeFunctionOnNextCall(load_poly);
140 var val = load_poly(o10);
142 assertFalse(o10.a == val);
144 // Ensure polymorphic loads only go monomorphic when the representations are
147 // Check polymorphic load from double + object fields.
148 function load_mono(o) {
152 var object = {"x": 1};
153 var o10 = { "a1": 1.6 };
154 var o11 = { "a1": object, "b": 1 };
158 %OptimizeFunctionOnNextCall(load_mono);
159 assertEquals(object, load_mono(o11));
161 // Check polymorphic load from smi + object fields.
162 function load_mono2(o) {
166 var o12 = { "a2": 5 };
167 var o13 = { "a2": object, "b": 1 };
171 %OptimizeFunctionOnNextCall(load_mono2);
172 assertEquals(object, load_mono2(o13));
174 // Check polymorphic load from double + double fields.
175 function load_mono3(o) {
179 var o14 = { "a3": 1.6 };
180 var o15 = { "a3": 1.8, "b": 1 };
184 %OptimizeFunctionOnNextCall(load_mono3);
185 assertEquals(1.6, load_mono3(o14));
186 assertEquals(1.8, load_mono3(o15));
188 // Check that JSON parsing respects existing representations.
189 var o16 = JSON.parse('{"a":1.5}');
190 var o17 = JSON.parse('{"a":100}');
191 assertTrue(%HaveSameMap(o16, o17));
193 assertEquals(100, o17_a);
195 assertEquals(100, o17_a);
196 assertEquals(200, o17.a);
198 // Ensure normalizing results in ignored representations.
209 assertFalse(%HaveSameMap(o18, o19));
211 delete o18.to_delete;
212 delete o19.to_delete;
214 assertEquals(1, o18.field2);
215 assertEquals(1.6, o19.field2);
217 // Test megamorphic keyed stub behaviour in combination with representations.
218 var some_object20 = {"a":1};
222 o20.obj = some_object20;
224 function keyed_load(o, k) {
228 function keyed_store(o, k, v) {
232 var smi20 = keyed_load(o20, "smi");
233 var dbl20 = keyed_load(o20, "dbl");
234 var obj20 = keyed_load(o20, "obj");
235 keyed_load(o20, "smi");
236 keyed_load(o20, "dbl");
237 keyed_load(o20, "obj");
238 keyed_load(o20, "smi");
239 keyed_load(o20, "dbl");
240 keyed_load(o20, "obj");
242 assertEquals(1, smi20);
243 assertEquals(1.5, dbl20);
244 assertEquals(some_object20, obj20);
246 keyed_store(o20, "smi", 100);
247 keyed_store(o20, "dbl", 100);
248 keyed_store(o20, "obj", 100);
249 keyed_store(o20, "smi", 100);
250 keyed_store(o20, "dbl", 100);
251 keyed_store(o20, "obj", 100);
252 keyed_store(o20, "smi", 100);
253 keyed_store(o20, "dbl", 100);
254 keyed_store(o20, "obj", 100);
256 assertEquals(1, smi20);
257 assertEquals(1.5, dbl20);
258 assertEquals(some_object20, obj20);
260 assertEquals(100, o20.smi);
261 assertEquals(100, o20.dbl);
262 assertEquals(100, o20.dbl);
264 function attr_mismatch_obj(v, writable) {
267 Object.defineProperty(o, "second_value", {value:10, writable:writable});
271 function is_writable(o, p) {
272 return Object.getOwnPropertyDescriptor(o,p).writable;
275 var writable = attr_mismatch_obj(10, true);
276 var non_writable1 = attr_mismatch_obj(10.5, false);
277 assertTrue(is_writable(writable,"second_value"));
278 assertFalse(is_writable(non_writable1,"second_value"));
279 writable.some_value = 20.5;
280 assertTrue(is_writable(writable,"second_value"));
281 var non_writable2 = attr_mismatch_obj(10.5, false);
282 assertTrue(%HaveSameMap(non_writable1, non_writable2));
291 function test_fic(o) {
295 var ftest1 = test_f(10);
296 var ftest2 = test_f(10);
297 var ftest3 = test_f(10.5);
298 var ftest4 = test_f(10);
299 assertFalse(%HaveSameMap(ftest1, ftest3));
300 assertTrue(%HaveSameMap(ftest3, ftest4));
301 ftest2.func = is_writable;
306 assertTrue(%HaveSameMap(ftest1, ftest3));
307 assertTrue(%HaveSameMap(ftest3, ftest4));
309 // Test representations and transition conversions.
310 function read_first_double(o) {
311 return o.first_double;
314 df1.first_double=1.6;
315 read_first_double(df1);
316 read_first_double(df1);
317 function some_function1() { return 10; }
319 df2.first_double = 1.7;
320 df2.second_function = some_function1;
321 function some_function2() { return 20; }
323 df3.first_double = 1.7;
324 df3.second_function = some_function2;
325 df1.first_double = 10;
326 read_first_double(df1);
328 // Test boilerplates with computed values.
329 function none_boilerplate(a) {
332 %OptimizeFunctionOnNextCall(none_boilerplate);
333 var none_double1 = none_boilerplate(1.7);
334 var none_double2 = none_boilerplate(1.9);
335 assertTrue(%HaveSameMap(none_double1, none_double2));
336 assertEquals(1.7, none_double1.a_none);
337 assertEquals(1.9, none_double2.a_none);
338 none_double2.a_none = 3.5;
339 var none_double1 = none_boilerplate(1.7);
340 var none_double2 = none_boilerplate(3.5);
342 function none_to_smi(a) {
346 var none_smi1 = none_to_smi(1);
347 var none_smi2 = none_to_smi(2);
348 %OptimizeFunctionOnNextCall(none_to_smi);
349 var none_smi3 = none_to_smi(3);
350 assertTrue(%HaveSameMap(none_smi1, none_smi2));
351 assertTrue(%HaveSameMap(none_smi1, none_smi3));
352 assertEquals(1, none_smi1.a_smi);
353 assertEquals(2, none_smi2.a_smi);
354 assertEquals(3, none_smi3.a_smi);
356 function none_to_double(a) {
357 return {"a_double":a};
360 var none_to_double1 = none_to_double(1.5);
361 var none_to_double2 = none_to_double(2.8);
362 %OptimizeFunctionOnNextCall(none_to_double);
363 var none_to_double3 = none_to_double(3.7);
364 assertTrue(%HaveSameMap(none_to_double1, none_to_double2));
365 assertTrue(%HaveSameMap(none_to_double1, none_to_double3));
366 assertEquals(1.5, none_to_double1.a_double);
367 assertEquals(2.8, none_to_double2.a_double);
368 assertEquals(3.7, none_to_double3.a_double);
370 function none_to_object(a) {
371 return {"an_object":a};
374 var none_to_object1 = none_to_object(true);
375 var none_to_object2 = none_to_object(false);
376 %OptimizeFunctionOnNextCall(none_to_object);
377 var none_to_object3 = none_to_object(3.7);
378 assertTrue(%HaveSameMap(none_to_object1, none_to_object2));
379 assertTrue(%HaveSameMap(none_to_object1, none_to_object3));
380 assertEquals(true, none_to_object1.an_object);
381 assertEquals(false, none_to_object2.an_object);
382 assertEquals(3.7, none_to_object3.an_object);
384 function double_to_object(a) {
385 var o = {"d_to_h":1.8};
390 var dh1 = double_to_object(true);
391 var dh2 = double_to_object(false);
392 assertTrue(%HaveSameMap(dh1, dh2));
393 assertEquals(true, dh1.d_to_h);
394 assertEquals(false, dh2.d_to_h);
396 function smi_to_object(a) {
397 var o = {"s_to_t":18};
402 var st1 = smi_to_object(true);
403 var st2 = smi_to_object(false);
404 assertTrue(%HaveSameMap(st1, st2));
405 assertEquals(true, st1.s_to_t);
406 assertEquals(false, st2.s_to_t);