The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / test / mjsunit / allocation-site-info.js @ f230a1cf

History | View | Annotate | Download (16.1 KB)

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 --smi-only-arrays --expose-gc
29
// Flags: --track-allocation-sites --noalways-opt
30

    
31
// Test element kind of objects.
32
// Since --smi-only-arrays affects builtins, its default setting at compile
33
// time sticks if built with snapshot.  If --smi-only-arrays is deactivated
34
// by default, only a no-snapshot build actually has smi-only arrays enabled
35
// in this test case.  Depending on whether smi-only arrays are actually
36
// enabled, this test takes the appropriate code path to check smi-only arrays.
37

    
38
// Reset the GC stress mode to be off. Needed because AllocationMementos only
39
// live for one gc, so a gc that happens in certain fragile areas of the test
40
// can break assumptions.
41
%SetFlags("--gc-interval=-1")
42

    
43
// support_smi_only_arrays = %HasFastSmiElements(new Array(1,2,3,4,5,6,7,8));
44
support_smi_only_arrays = true;
45

    
46
if (support_smi_only_arrays) {
47
  print("Tests include smi-only arrays.");
48
} else {
49
  print("Tests do NOT include smi-only arrays.");
50
}
51

    
52
var elements_kind = {
53
  fast_smi_only            :  'fast smi only elements',
54
  fast                     :  'fast elements',
55
  fast_double              :  'fast double elements',
56
  dictionary               :  'dictionary elements',
57
  external_byte            :  'external byte elements',
58
  external_unsigned_byte   :  'external unsigned byte elements',
59
  external_short           :  'external short elements',
60
  external_unsigned_short  :  'external unsigned short elements',
61
  external_int             :  'external int elements',
62
  external_unsigned_int    :  'external unsigned int elements',
63
  external_float           :  'external float elements',
64
  external_double          :  'external double elements',
65
  external_pixel           :  'external pixel elements'
66
}
67

    
68
function getKind(obj) {
69
  if (%HasFastSmiElements(obj)) return elements_kind.fast_smi_only;
70
  if (%HasFastObjectElements(obj)) return elements_kind.fast;
71
  if (%HasFastDoubleElements(obj)) return elements_kind.fast_double;
72
  if (%HasDictionaryElements(obj)) return elements_kind.dictionary;
73
}
74

    
75
function isHoley(obj) {
76
  if (%HasFastHoleyElements(obj)) return true;
77
  return false;
78
}
79

    
80
function assertKind(expected, obj, name_opt) {
81
  if (!support_smi_only_arrays &&
82
      expected == elements_kind.fast_smi_only) {
83
    expected = elements_kind.fast;
84
  }
85
  assertEquals(expected, getKind(obj), name_opt);
86
}
87

    
88
function assertHoley(obj, name_opt) {
89
  assertEquals(true, isHoley(obj), name_opt);
90
}
91

    
92
function assertNotHoley(obj, name_opt) {
93
  assertEquals(false, isHoley(obj), name_opt);
94
}
95

    
96
if (support_smi_only_arrays) {
97
  obj = [];
98
  assertNotHoley(obj);
99
  assertKind(elements_kind.fast_smi_only, obj);
100

    
101
  obj = [1, 2, 3];
102
  assertNotHoley(obj);
103
  assertKind(elements_kind.fast_smi_only, obj);
104

    
105
  obj = new Array();
106
  assertNotHoley(obj);
107
  assertKind(elements_kind.fast_smi_only, obj);
108

    
109
  obj = new Array(0);
110
  assertNotHoley(obj);
111
  assertKind(elements_kind.fast_smi_only, obj);
112

    
113
  obj = new Array(2);
114
  assertHoley(obj);
115
  assertKind(elements_kind.fast_smi_only, obj);
116

    
117
  obj = new Array(1,2,3);
118
  assertNotHoley(obj);
119
  assertKind(elements_kind.fast_smi_only, obj);
120

    
121
  obj = new Array(1, "hi", 2, undefined);
122
  assertNotHoley(obj);
123
  assertKind(elements_kind.fast, obj);
124

    
125
  function fastliteralcase(literal, value) {
126
    literal[0] = value;
127
    return literal;
128
  }
129

    
130
  function get_standard_literal() {
131
    var literal = [1, 2, 3];
132
    return literal;
133
  }
134

    
135
  // Case: [1,2,3] as allocation site
136
  obj = fastliteralcase(get_standard_literal(), 1);
137
  assertKind(elements_kind.fast_smi_only, obj);
138
  obj = fastliteralcase(get_standard_literal(), 1.5);
139
  assertKind(elements_kind.fast_double, obj);
140
  obj = fastliteralcase(get_standard_literal(), 2);
141
  assertKind(elements_kind.fast_double, obj);
142

    
143
  // The test below is in a loop because arrays that live
144
  // at global scope without the chance of being recreated
145
  // don't have allocation site information attached.
146
  for (i = 0; i < 2; i++) {
147
    obj = fastliteralcase([5, 3, 2], 1.5);
148
    assertKind(elements_kind.fast_double, obj);
149
    obj = fastliteralcase([3, 6, 2], 1.5);
150
    assertKind(elements_kind.fast_double, obj);
151
    obj = fastliteralcase([2, 6, 3], 2);
152
    assertKind(elements_kind.fast_smi_only, obj);
153
  }
154

    
155
  // Verify that we will not pretransition the double->fast path.
156
  obj = fastliteralcase(get_standard_literal(), "elliot");
157
  assertKind(elements_kind.fast, obj);
158
  obj = fastliteralcase(get_standard_literal(), 3);
159
  assertKind(elements_kind.fast, obj);
160

    
161
  // Make sure this works in crankshafted code too.
162
  %OptimizeFunctionOnNextCall(get_standard_literal);
163
  get_standard_literal();
164
  obj = get_standard_literal();
165
  assertKind(elements_kind.fast, obj);
166

    
167
  function fastliteralcase_smifast(value) {
168
    var literal = [1, 2, 3, 4];
169
    literal[0] = value;
170
    return literal;
171
  }
172

    
173
  obj = fastliteralcase_smifast(1);
174
  assertKind(elements_kind.fast_smi_only, obj);
175
  obj = fastliteralcase_smifast("carter");
176
  assertKind(elements_kind.fast, obj);
177
  obj = fastliteralcase_smifast(2);
178
  assertKind(elements_kind.fast, obj);
179

    
180
  // Case: make sure transitions from packed to holey are tracked
181
  function fastliteralcase_smiholey(index, value) {
182
    var literal = [1, 2, 3, 4];
183
    literal[index] = value;
184
    return literal;
185
  }
186

    
187
  obj = fastliteralcase_smiholey(5, 1);
188
  assertKind(elements_kind.fast_smi_only, obj);
189
  assertHoley(obj);
190
  obj = fastliteralcase_smiholey(0, 1);
191
  assertKind(elements_kind.fast_smi_only, obj);
192
  assertHoley(obj);
193

    
194
  function newarraycase_smidouble(value) {
195
    var a = new Array();
196
    a[0] = value;
197
    return a;
198
  }
199

    
200
  // Case: new Array() as allocation site, smi->double
201
  obj = newarraycase_smidouble(1);
202
  assertKind(elements_kind.fast_smi_only, obj);
203
  obj = newarraycase_smidouble(1.5);
204
  assertKind(elements_kind.fast_double, obj);
205
  obj = newarraycase_smidouble(2);
206
  assertKind(elements_kind.fast_double, obj);
207

    
208
  function newarraycase_smiobj(value) {
209
    var a = new Array();
210
    a[0] = value;
211
    return a;
212
  }
213

    
214
  // Case: new Array() as allocation site, smi->fast
215
  obj = newarraycase_smiobj(1);
216
  assertKind(elements_kind.fast_smi_only, obj);
217
  obj = newarraycase_smiobj("gloria");
218
  assertKind(elements_kind.fast, obj);
219
  obj = newarraycase_smiobj(2);
220
  assertKind(elements_kind.fast, obj);
221

    
222
  function newarraycase_length_smidouble(value) {
223
    var a = new Array(3);
224
    a[0] = value;
225
    return a;
226
  }
227

    
228
  // Case: new Array(length) as allocation site
229
  obj = newarraycase_length_smidouble(1);
230
  assertKind(elements_kind.fast_smi_only, obj);
231
  obj = newarraycase_length_smidouble(1.5);
232
  assertKind(elements_kind.fast_double, obj);
233
  obj = newarraycase_length_smidouble(2);
234
  assertKind(elements_kind.fast_double, obj);
235

    
236
  // Try to continue the transition to fast object. This won't work for
237
  // constructed arrays because constructor dispatch is done on the
238
  // elements kind, and a DOUBLE array constructor won't create an allocation
239
  // memento.
240
  obj = newarraycase_length_smidouble("coates");
241
  assertKind(elements_kind.fast, obj);
242
  obj = newarraycase_length_smidouble(2);
243
  assertKind(elements_kind.fast_double, obj);
244

    
245
  function newarraycase_length_smiobj(value) {
246
    var a = new Array(3);
247
    a[0] = value;
248
    return a;
249
  }
250

    
251
  // Case: new Array(<length>) as allocation site, smi->fast
252
  obj = newarraycase_length_smiobj(1);
253
  assertKind(elements_kind.fast_smi_only, obj);
254
  obj = newarraycase_length_smiobj("gloria");
255
  assertKind(elements_kind.fast, obj);
256
  obj = newarraycase_length_smiobj(2);
257
  assertKind(elements_kind.fast, obj);
258

    
259
  function newarraycase_list_smidouble(value) {
260
    var a = new Array(1, 2, 3);
261
    a[0] = value;
262
    return a;
263
  }
264

    
265
  obj = newarraycase_list_smidouble(1);
266
  assertKind(elements_kind.fast_smi_only, obj);
267
  obj = newarraycase_list_smidouble(1.5);
268
  assertKind(elements_kind.fast_double, obj);
269
  obj = newarraycase_list_smidouble(2);
270
  assertKind(elements_kind.fast_double, obj);
271

    
272
  function newarraycase_list_smiobj(value) {
273
    var a = new Array(4, 5, 6);
274
    a[0] = value;
275
    return a;
276
  }
277

    
278
  obj = newarraycase_list_smiobj(1);
279
  assertKind(elements_kind.fast_smi_only, obj);
280
  obj = newarraycase_list_smiobj("coates");
281
  assertKind(elements_kind.fast, obj);
282
  obj = newarraycase_list_smiobj(2);
283
  assertKind(elements_kind.fast, obj);
284

    
285
  // Case: array constructor calls with out of date feedback.
286
  // The boilerplate should incorporate all feedback, but the input array
287
  // should be minimally transitioned based on immediate need.
288
  (function() {
289
    function foo(i) {
290
      // We have two cases, one for literals one for constructed arrays.
291
      var a = (i == 0)
292
        ? [1, 2, 3]
293
        : new Array(1, 2, 3);
294
      return a;
295
    }
296

    
297
    for (i = 0; i < 2; i++) {
298
      a = foo(i);
299
      b = foo(i);
300
      b[5] = 1;  // boilerplate goes holey
301
      assertHoley(foo(i));
302
      a[0] = 3.5;  // boilerplate goes holey double
303
      assertKind(elements_kind.fast_double, a);
304
      assertNotHoley(a);
305
      c = foo(i);
306
      assertKind(elements_kind.fast_double, c);
307
      assertHoley(c);
308
    }
309
  })();
310

    
311
  function newarraycase_onearg(len, value) {
312
    var a = new Array(len);
313
    a[0] = value;
314
    return a;
315
  }
316

    
317
  obj = newarraycase_onearg(5, 3.5);
318
  assertKind(elements_kind.fast_double, obj);
319
  obj = newarraycase_onearg(10, 5);
320
  assertKind(elements_kind.fast_double, obj);
321
  obj = newarraycase_onearg(0, 5);
322
  assertKind(elements_kind.fast_double, obj);
323
  // Now pass a length that forces the dictionary path.
324
  obj = newarraycase_onearg(100000, 5);
325
  assertKind(elements_kind.dictionary, obj);
326
  assertTrue(obj.length == 100000);
327

    
328
  // Verify that cross context calls work
329
  var realmA = Realm.current();
330
  var realmB = Realm.create();
331
  assertEquals(0, realmA);
332
  assertEquals(1, realmB);
333

    
334
  function instanceof_check(type) {
335
    assertTrue(new type() instanceof type);
336
    assertTrue(new type(5) instanceof type);
337
    assertTrue(new type(1,2,3) instanceof type);
338
  }
339

    
340
  function instanceof_check2(type) {
341
    assertTrue(new type() instanceof type);
342
    assertTrue(new type(5) instanceof type);
343
    assertTrue(new type(1,2,3) instanceof type);
344
  }
345

    
346
  var realmBArray = Realm.eval(realmB, "Array");
347
  instanceof_check(Array);
348
  instanceof_check(realmBArray);
349

    
350
  // instanceof_check2 is here because the call site goes through a state.
351
  // Since instanceof_check(Array) was first called with the current context
352
  // Array function, it went from (uninit->Array) then (Array->megamorphic).
353
  // We'll get a different state traversal if we start with realmBArray.
354
  // It'll go (uninit->realmBArray) then (realmBArray->megamorphic). Recognize
355
  // that state "Array" implies an AllocationSite is present, and code is
356
  // configured to use it.
357
  instanceof_check2(realmBArray);
358
  instanceof_check2(Array);
359

    
360
  %OptimizeFunctionOnNextCall(instanceof_check);
361

    
362
  // No de-opt will occur because HCallNewArray wasn't selected, on account of
363
  // the call site not being monomorphic to Array.
364
  instanceof_check(Array);
365
  assertOptimized(instanceof_check);
366
  instanceof_check(realmBArray);
367
  assertOptimized(instanceof_check);
368

    
369
  // Try to optimize again, but first clear all type feedback, and allow it
370
  // to be monomorphic on first call. Only after crankshafting do we introduce
371
  // realmBArray. This should deopt the method.
372
  %DeoptimizeFunction(instanceof_check);
373
  %ClearFunctionTypeFeedback(instanceof_check);
374
  instanceof_check(Array);
375
  instanceof_check(Array);
376
  %OptimizeFunctionOnNextCall(instanceof_check);
377
  instanceof_check(Array);
378
  assertOptimized(instanceof_check);
379

    
380
  instanceof_check(realmBArray);
381
  assertUnoptimized(instanceof_check);
382

    
383
  // Case: make sure nested arrays benefit from allocation site feedback as
384
  // well.
385
  (function() {
386
    // Make sure we handle nested arrays
387
   function get_nested_literal() {
388
     var literal = [[1,2,3,4], [2], [3]];
389
     return literal;
390
   }
391

    
392
   obj = get_nested_literal();
393
   assertKind(elements_kind.fast, obj);
394
   obj[0][0] = 3.5;
395
   obj[2][0] = "hello";
396
   obj = get_nested_literal();
397
   assertKind(elements_kind.fast_double, obj[0]);
398
   assertKind(elements_kind.fast_smi_only, obj[1]);
399
   assertKind(elements_kind.fast, obj[2]);
400

    
401
   // A more complex nested literal case.
402
   function get_deep_nested_literal() {
403
     var literal = [[1], [[2], "hello"], 3, [4]];
404
     return literal;
405
   }
406

    
407
   obj = get_deep_nested_literal();
408
   assertKind(elements_kind.fast_smi_only, obj[1][0]);
409
   obj[0][0] = 3.5;
410
   obj[1][0][0] = "goodbye";
411
   assertKind(elements_kind.fast_double, obj[0]);
412
   assertKind(elements_kind.fast, obj[1][0]);
413

    
414
   obj = get_deep_nested_literal();
415
   assertKind(elements_kind.fast_double, obj[0]);
416
   assertKind(elements_kind.fast, obj[1][0]);
417
  })();
418

    
419

    
420
  // Make sure object literals with array fields benefit from the type feedback
421
  // that allocation mementos provide.
422
  (function() {
423
    // A literal in an object
424
    function get_object_literal() {
425
      var literal = {
426
        array: [1,2,3],
427
        data: 3.5
428
      };
429
      return literal;
430
    }
431

    
432
    obj = get_object_literal();
433
    assertKind(elements_kind.fast_smi_only, obj.array);
434
    obj.array[1] = 3.5;
435
    assertKind(elements_kind.fast_double, obj.array);
436
    obj = get_object_literal();
437
    assertKind(elements_kind.fast_double, obj.array);
438

    
439
    function get_nested_object_literal() {
440
      var literal = {
441
        array: [[1],[2],[3]],
442
        data: 3.5
443
      };
444
      return literal;
445
    }
446

    
447
    obj = get_nested_object_literal();
448
    assertKind(elements_kind.fast, obj.array);
449
    assertKind(elements_kind.fast_smi_only, obj.array[1]);
450
    obj.array[1][0] = 3.5;
451
    assertKind(elements_kind.fast_double, obj.array[1]);
452
    obj = get_nested_object_literal();
453
    assertKind(elements_kind.fast_double, obj.array[1]);
454

    
455
    %OptimizeFunctionOnNextCall(get_nested_object_literal);
456
    get_nested_object_literal();
457
    obj = get_nested_object_literal();
458
    assertKind(elements_kind.fast_double, obj.array[1]);
459

    
460
    // Make sure we handle nested arrays
461
    function get_nested_literal() {
462
      var literal = [[1,2,3,4], [2], [3]];
463
      return literal;
464
    }
465

    
466
    obj = get_nested_literal();
467
    assertKind(elements_kind.fast, obj);
468
    obj[0][0] = 3.5;
469
    obj[2][0] = "hello";
470
    obj = get_nested_literal();
471
    assertKind(elements_kind.fast_double, obj[0]);
472
    assertKind(elements_kind.fast_smi_only, obj[1]);
473
    assertKind(elements_kind.fast, obj[2]);
474

    
475
    // A more complex nested literal case.
476
    function get_deep_nested_literal() {
477
      var literal = [[1], [[2], "hello"], 3, [4]];
478
      return literal;
479
    }
480

    
481
    obj = get_deep_nested_literal();
482
    assertKind(elements_kind.fast_smi_only, obj[1][0]);
483
    obj[0][0] = 3.5;
484
    obj[1][0][0] = "goodbye";
485
    assertKind(elements_kind.fast_double, obj[0]);
486
    assertKind(elements_kind.fast, obj[1][0]);
487

    
488
    obj = get_deep_nested_literal();
489
    assertKind(elements_kind.fast_double, obj[0]);
490
    assertKind(elements_kind.fast, obj[1][0]);
491
  })();
492
}