bug1494537-plain.js (3350B)
1 // Version of bug1494537.js for plain objects. 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_object(obj, count, epsilon = 0) { 19 var index = 0; 20 for (var i = 0; i < count; i++) { 21 index = update_index(index, i); 22 obj[index] = i + epsilon; 23 } 24 return obj[offsets[0]+offsets[1]] === (1 + epsilon) && 25 obj[10] === undefined; 26 } 27 28 // Monomorphizing mutate_object to ensure we get the IC chains we want 29 function create_variant(variant) { 30 var source = mutate_object.toString().replace("mutate_object", "mutate_object_"+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_object_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_object_frozen(x, count), false); 53 54 var end = compute_index(0, count); 55 56 var y = {}; 57 assertEq(mutate_object_frozen(y, count), true); 58 assertEq(y[end], count - 1); 59 Object.freeze(y); 60 61 // After a mutated object is frozen, can't subsequently modify elements 62 assertEq(mutate_object_frozen(x, count, 10), false); 63 assertEq(y[end], count - 1); 64 } 65 66 // Let's make sure updates to the object happen as expected. 67 function test_update() { 68 eval(create_variant("update")); 69 70 var x = {}; 71 var count = 100; 72 assertEq(mutate_object_update(x, count), true); 73 var end = compute_index(0, count); 74 assertEq(x[end], count - 1); 75 assertEq(x[end - 1], undefined); 76 77 var epsilon = 2; 78 mutate_object_update(x, 200, epsilon); 79 assertEq(x[end], count -1 + epsilon) 80 } 81 82 // Elements may be non-writable, let us not write them. 83 function test_nonwritable() { 84 eval(create_variant("nonwritable")); 85 var x = {}; 86 var count = 100; 87 var index = compute_index(0, 10); 88 Object.defineProperty(x, index, {value: -10, writable: false}); 89 mutate_object_nonwritable(x, count); 90 assertEq(x[index], -10); 91 } 92 93 // Random indices can get setters, let's make sure we honour those. 94 function test_setter() { 95 eval(create_variant("setter")); 96 var x = {}; 97 var count = 100; 98 var index = compute_index(0, 80); 99 var sigil = 0; 100 Object.defineProperty(x, index, {set(newVal) {sigil++; }}); 101 mutate_object_setter(x, count); 102 assertEq(sigil, 1); 103 assertEq(x[index], undefined); 104 } 105 106 // Ensure indexes on the prototype don't break things. 107 function test_proto_indices() { 108 eval(create_variant("proto_indices")); 109 var x = {}; 110 var count = 100; 111 var index = compute_index(0, 80); 112 x.__proto__[index] = "hello"; 113 mutate_object_proto_indices(x, count); 114 assertEq(x.__proto__[index], "hello"); 115 assertEq(x[index], 79); 116 } 117 118 test_basic(); 119 test_frozen(); 120 test_update(); 121 test_nonwritable(); 122 test_setter(); 123 test_proto_indices();