Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / v8 / test / mjsunit / track-fields.js
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
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: --track-fields --track-double-fields --allow-natives-syntax
29
30 // Test transitions caused by changes to field representations.
31
32 function create_smi_object() {
33   var o = {};
34   o.x = 1;
35   o.y = 2;
36   o.z = 3;
37   return o;
38 }
39
40 var o1 = create_smi_object();
41 var o2 = create_smi_object();
42
43 // o1,o2 are smi, smi, smi
44 assertTrue(%HaveSameMap(o1, o2));
45 o1.y = 1.3;
46 // o1 is smi, double, smi
47 assertFalse(%HaveSameMap(o1, o2));
48 o2.y = 1.5;
49 // o2 is smi, double, smi
50 assertTrue(%HaveSameMap(o1, o2));
51
52 // o3 is initialized as smi, double, smi
53 var o3 = create_smi_object();
54 assertTrue(%HaveSameMap(o1, o3));
55
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;
66 }
67
68 // Check that large object migrations work.
69 var o4 = {};
70 // All smi.
71 set_large(o4, 0);
72 assertTrue(%HasFastProperties(o4));
73 // All double.
74 set_large(o4, 1.5);
75 // o5 is immediately allocated with doubles.
76 var o5 = {};
77 set_large(o5, 0);
78 assertTrue(%HaveSameMap(o4, o5));
79
80 function create_smi_object2() {
81   var o = {};
82   o.a = 1;
83   o.b = 2;
84   o.c = 3;
85   return o;
86 }
87
88 // All smi
89 var o6 = create_smi_object2();
90 var o7 = create_smi_object2();
91
92 assertTrue(%HaveSameMap(o6, o7));
93 // Smi, double, smi.
94 o6.b = 1.5;
95 assertFalse(%HaveSameMap(o6, o7));
96 // Smi, double, object.
97 o7.c = {};
98 assertFalse(%HaveSameMap(o6, o7));
99 // Smi, double, object.
100 o6.c = {};
101 assertTrue(%HaveSameMap(o6, o7));
102
103 function poly_load(o, b) {
104   var v = o.field;
105   if (b) {
106     return v + 10;
107   }
108   return o;
109 }
110
111 var of1 = {a:0};
112 of1.field = {};
113 var of2 = {b:0};
114 of2.field = 10;
115
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));
121
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();
126 o8.a = 4.6
127 assertEquals(1.5, o9.a);
128
129 // Ensure double storage is not leaked in the case of polymorphic loads.
130 function load_poly(o) {
131   return o.a;
132 }
133
134 var o10 = { "a": 1.6 };
135 var o11 = { "b": 1, "a": 1.7 };
136 load_poly(o10);
137 load_poly(o10);
138 load_poly(o11);
139 %OptimizeFunctionOnNextCall(load_poly);
140 var val = load_poly(o10);
141 o10.a = 19.5;
142 assertFalse(o10.a == val);
143
144 // Ensure polymorphic loads only go monomorphic when the representations are
145 // compatible.
146
147 // Check polymorphic load from double + object fields.
148 function load_mono(o) {
149   return o.a1;
150 }
151
152 var object = {"x": 1};
153 var o10 = { "a1": 1.6 };
154 var o11 = { "a1": object, "b": 1 };
155 load_mono(o10);
156 load_mono(o10);
157 load_mono(o11);
158 %OptimizeFunctionOnNextCall(load_mono);
159 assertEquals(object, load_mono(o11));
160
161 // Check polymorphic load from smi + object fields.
162 function load_mono2(o) {
163   return o.a2;
164 }
165
166 var o12 = { "a2": 5 };
167 var o13 = { "a2": object, "b": 1 };
168 load_mono2(o12);
169 load_mono2(o12);
170 load_mono2(o13);
171 %OptimizeFunctionOnNextCall(load_mono2);
172 assertEquals(object, load_mono2(o13));
173
174 // Check polymorphic load from double + double fields.
175 function load_mono3(o) {
176   return o.a3;
177 }
178
179 var o14 = { "a3": 1.6 };
180 var o15 = { "a3": 1.8, "b": 1 };
181 load_mono3(o14);
182 load_mono3(o14);
183 load_mono3(o15);
184 %OptimizeFunctionOnNextCall(load_mono3);
185 assertEquals(1.6, load_mono3(o14));
186 assertEquals(1.8, load_mono3(o15));
187
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));
192 var o17_a = o17.a;
193 assertEquals(100, o17_a);
194 o17.a = 200;
195 assertEquals(100, o17_a);
196 assertEquals(200, o17.a);
197
198 // Ensure normalizing results in ignored representations.
199 var o18 = {};
200 o18.field1 = 100;
201 o18.field2 = 1;
202 o18.to_delete = 100;
203
204 var o19 = {};
205 o19.field1 = 100;
206 o19.field2 = 1.6;
207 o19.to_delete = 100;
208
209 assertFalse(%HaveSameMap(o18, o19));
210
211 delete o18.to_delete;
212 delete o19.to_delete;
213
214 assertEquals(1, o18.field2);
215 assertEquals(1.6, o19.field2);
216
217 // Test megamorphic keyed stub behaviour in combination with representations.
218 var some_object20 = {"a":1};
219 var o20 = {};
220 o20.smi = 1;
221 o20.dbl = 1.5;
222 o20.obj = some_object20;
223
224 function keyed_load(o, k) {
225   return o[k];
226 }
227
228 function keyed_store(o, k, v) {
229   return o[k] = v;
230 }
231
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");
241
242 assertEquals(1, smi20);
243 assertEquals(1.5, dbl20);
244 assertEquals(some_object20, obj20);
245
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);
255
256 assertEquals(1, smi20);
257 assertEquals(1.5, dbl20);
258 assertEquals(some_object20, obj20);
259
260 assertEquals(100, o20.smi);
261 assertEquals(100, o20.dbl);
262 assertEquals(100, o20.dbl);
263
264 function attr_mismatch_obj(v, writable) {
265   var o = {};
266   o.some_value = v;
267   Object.defineProperty(o, "second_value", {value:10, writable:writable});
268   return o;
269 }
270
271 function is_writable(o, p) {
272   return Object.getOwnPropertyDescriptor(o,p).writable;
273 }
274
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));
283
284 function test_f(v) {
285   var o = {};
286   o.vbf = v;
287   o.func = test_f;
288   return o;
289 }
290
291 function test_fic(o) {
292   return o.vbf;
293 }
294
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;
302 test_fic(ftest1);
303 test_fic(ftest2);
304 test_fic(ftest3);
305 test_fic(ftest4);
306 assertTrue(%HaveSameMap(ftest1, ftest3));
307 assertTrue(%HaveSameMap(ftest3, ftest4));
308
309 // Test representations and transition conversions.
310 function read_first_double(o) {
311   return o.first_double;
312 }
313 var df1 = {};
314 df1.first_double=1.6;
315 read_first_double(df1);
316 read_first_double(df1);
317 function some_function1() { return 10; }
318 var df2 = {};
319 df2.first_double = 1.7;
320 df2.second_function = some_function1;
321 function some_function2() { return 20; }
322 var df3 = {};
323 df3.first_double = 1.7;
324 df3.second_function = some_function2;
325 df1.first_double = 10;
326 read_first_double(df1);
327
328 // Test boilerplates with computed values.
329 function none_boilerplate(a) {
330   return {"a_none":a};
331 }
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);
341
342 function none_to_smi(a) {
343   return {"a_smi":a};
344 }
345
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);
355
356 function none_to_double(a) {
357   return {"a_double":a};
358 }
359
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);
369
370 function none_to_object(a) {
371   return {"an_object":a};
372 }
373
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);
383
384 function double_to_object(a) {
385   var o = {"d_to_h":1.8};
386   o.d_to_h = a;
387   return o;
388 }
389
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);
395
396 function smi_to_object(a) {
397   var o = {"s_to_t":18};
398   o.s_to_t = a;
399   return o;
400 }
401
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);