bug1494537.js (3375B)
1 setJitCompilerOption("ion.forceinlineCaches", 1); 2 3 let offsets = [213, 559, 255, 515, 30, 507, 252, 329, 487, 7]; 4 5 function update_index(i, j) { 6 var offset = offsets[j % offsets.length]; 7 return i + offset; 8 } 9 10 function compute_index(initial, count) { 11 for (var i = 0; i < count; i++) { 12 initial = update_index(initial, i); 13 } 14 return initial; 15 } 16 17 // This is written so that the IC added in the bug activates. 18 function mutate_array(array, count, epsilon = 0) { 19 var index = 0; 20 for (var i = 0; i < count; i++) { 21 index = update_index(index, i); 22 array[index] = i + epsilon; 23 } 24 return array[offsets[0]+offsets[1]] === (1 + epsilon) && 25 array[10] === undefined; 26 } 27 28 // Monomorphizing mutate_array to ensure we get the IC chains we want 29 function create_variant(variant) { 30 var source = mutate_array.toString().replace("mutate_array", "mutate_array_"+variant); 31 return source; 32 } 33 34 function test_basic() { 35 eval(create_variant("basic")); 36 var x = []; 37 38 var count = 100; 39 assertEq(mutate_array_basic(x, count), true); 40 var end = compute_index(0, count); 41 assertEq(x[end], count - 1); 42 assertEq(x[end - 1], undefined); 43 } 44 45 // Ensure the IC respects frozen. 46 function test_frozen() { 47 eval(create_variant("frozen")); 48 var x = []; 49 Object.freeze(x); 50 51 var count = 100; 52 assertEq(mutate_array_frozen(x, count), false); 53 assertEq(x.length, 0); 54 55 var end = compute_index(0, count); 56 57 var y = []; 58 assertEq(mutate_array_frozen(y, count), true); 59 assertEq(y[end], count - 1); 60 Object.freeze(y); 61 62 // After a mutated array is frozen, can't subsequently modify elements 63 assertEq(mutate_array_frozen(x, count, 10), false); 64 assertEq(y[end], count - 1); 65 } 66 67 // Let's make sure updates to the array happen as expected. 68 function test_update() { 69 eval(create_variant("update")); 70 71 var x = []; 72 var count = 100; 73 assertEq(mutate_array_update(x, count), true); 74 var end = compute_index(0, count); 75 assertEq(x[end], count - 1); 76 assertEq(x[end - 1], undefined); 77 78 var epsilon = 2; 79 mutate_array_update(x, 200, epsilon); 80 assertEq(x[end], count -1 + epsilon) 81 } 82 83 // Elements may be non-writable, let us not write them. 84 function test_nonwritable() { 85 eval(create_variant("nonwritable")); 86 var x = []; 87 var count = 100; 88 var index = compute_index(0, 10); 89 Object.defineProperty(x, index, {value: -10, writable: false}); 90 mutate_array_nonwritable(x, count); 91 assertEq(x[index], -10); 92 } 93 94 // Random indices can get setters, let's make sure we honour those. 95 function test_setter() { 96 eval(create_variant("setter")); 97 var x = []; 98 var count = 100; 99 var index = compute_index(0, 80); 100 var sigil = 0; 101 Object.defineProperty(x, index, {set(newVal) {sigil++; }}); 102 mutate_array_setter(x, count); 103 assertEq(sigil, 1); 104 assertEq(x[index], undefined); 105 } 106 107 // Ensure indexes on the prototype don't break things; 108 // 109 function test_proto_indices() { 110 eval(create_variant("proto_indices")); 111 var x = []; 112 var count = 100; 113 var index = compute_index(0, 80); 114 x.__proto__[index] = "hello"; 115 mutate_array_proto_indices(x, count); 116 assertEq(x.__proto__[index], "hello"); 117 assertEq(x[index], 79); 118 } 119 120 test_basic(); 121 test_frozen(); 122 test_update(); 123 test_nonwritable(); 124 test_setter(); 125 test_proto_indices();