summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/ion/fromcharcode-charcodeat-zero.js
blob: b8a5cb6b561f1cb41d6def89c90653e5b84d51ca (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
function toCharCodes(str) {
  return [...str].map(s => s.length === 1 ? [s.charCodeAt(0)] : [s.charCodeAt(0), s.charCodeAt(1)])
                 .flat();
}

function test() {
  // [Ascii; Latin-1, non-Ascii; non-Latin-1; non-BMP]
  const constant = "AaÁáĀā𝐀𝐚";
  const charCodes = toCharCodes(constant);

  // Create a linear, but non-constant string with the same contents.
  const linear = String.fromCharCode(...charCodes);
  assertEq(linear, constant);

  // Optimisation applies for |MCharCodeAt(MFromCharCode(MCharCodeAt(str, idx)), 0|.
  for (let i = 0; i < 500; ++i) {
    let idx = i & 3;

    // str[idx] is compiled to |MFromCharCode(MCharCodeAt(str, idx))|.
    assertEq(constant[idx].charCodeAt(0), charCodes[idx]);
    assertEq(linear[idx].charCodeAt(0), charCodes[idx]);

    // str.charAt(idx) is compiled to |MFromCharCode(MCharCodeAt(str, idx))|.
    assertEq(constant.charAt(idx).charCodeAt(0), charCodes[idx]);
    assertEq(linear.charAt(idx).charCodeAt(0), charCodes[idx]);
  }
}
for (let i = 0; i < 4; ++i) {
  test();
}

function testNonConstantIndex() {
  // [Ascii; Latin-1, non-Ascii; non-Latin-1; non-BMP]
  const constant = "AaÁáĀā𝐀𝐚";
  const charCodes = toCharCodes(constant);

  // Create a linear, but non-constant string with the same contents.
  const linear = String.fromCharCode(...charCodes);
  assertEq(linear, constant);

  // No optimisation when the index isn't a constant zero.
  let indices = [0, 1, 2, 3];
  for (let i = 0; i < 500; ++i) {
    let idx = i & 3;

    // Always zero, but too complicated to infer at compile time.
    let zero = indices[idx] - idx;

    assertEq(constant[idx].charCodeAt(zero), charCodes[idx]);
    assertEq(linear[idx].charCodeAt(zero), charCodes[idx]);

    assertEq(constant.charAt(idx).charCodeAt(zero), charCodes[idx]);
    assertEq(linear.charAt(idx).charCodeAt(zero), charCodes[idx]);
  }
}
for (let i = 0; i < 4; ++i) {
  testNonConstantIndex();
}

function testOOB() {
  // [Ascii; Latin-1, non-Ascii; non-Latin-1; non-BMP]
  const constant = "AaÁáĀā𝐀𝐚";
  const charCodes = toCharCodes(constant);

  // Create a linear, but non-constant string with the same contents.
  const linear = String.fromCharCode(...charCodes);
  assertEq(linear, constant);

  // No optimisation when the index is out-of-bounds.
  for (let i = 0; i < 500; ++i) {
    let idx = i & 3;

    assertEq(constant[idx].charCodeAt(1), NaN);
    assertEq(linear[idx].charCodeAt(1), NaN);

    assertEq(constant.charAt(idx).charCodeAt(1), NaN);
    assertEq(linear.charAt(idx).charCodeAt(1), NaN);
  }
}
for (let i = 0; i < 4; ++i) {
  testOOB();
}