1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2009 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// Test paths in the code generator where values in specific registers
29402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// get moved around.
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction identity(x) {
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return x;
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
346ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockfunction lookup(w, a) {
356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // This function tests a code path in the generation of a keyed load IC
366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // where the key and the value are both in the same register.
376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  a = a;
386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  w[a] = a;
396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction cover_codegen_paths() {
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var x = 1;
43402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
44402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // This test depends on the fixed order of register allocation.  We try to
45402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // get values in specific registers (ia32, x64):
46402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  var a;   // Register eax, rax.
47402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  var b;   // Register ebx, rbx.
48402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  var c;   // Register ecx, rcx.
49402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  var d;   // Register edx, rdx.
50402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  var di;  // Register edi, rdi.
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (x == 1) {
53402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // The call will spill registers and leave x in {eax,rax}.
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    x = identity(1);
55402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // The add will spill x and reuse {eax,rax} for the result.
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    a = x + 1;
57402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // A fresh register {ebx,rbx} will be allocated for x, then reused for
58402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // the result.
59402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    b = x + 1;
60402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // Et cetera.
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    c = x + 1;
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    d = x + 1;
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    di = x + 1;
64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Locals are in the corresponding registers here.
65402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    assertEquals(8, c << a);
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    x = identity(1);
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    a = x + 1;
69402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    b = x + 1;
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    c = x + 1;
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    d = x + 1;
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    di = x + 1;
73402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    assertEquals(8, a << c);
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    x = identity(1);
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    a = x + 1;
77402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    b = x + 1;
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    c = x + 1;
79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    d = x + 1;
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    di = x + 1;
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    c = 0; // Free register ecx.
82402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    assertEquals(8, a << d);
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    x = identity(1);
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    a = x + 1;
86402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    b = x + 1;
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    c = x + 1;
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    d = x + 1;
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    di = x + 1;
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    b = 0; // Free register ebx.
91402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    assertEquals(8, a << d);
92402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
93402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // Test the non-commutative subtraction operation with a smi on the
94402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // left, all available registers on the right, and a non-smi result.
95402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    x = identity(-1073741824);  // Least (31-bit) smi.
96402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    a = x + 1;  // Still a smi, the greatest smi negated.
97402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    b = x + 1;
98402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    c = x + 1;
99402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    d = x + 1;
100402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    di = x + 1;
101402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // Subtraction should overflow the 31-bit smi range.  The result
102402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // (1073741824) is outside the 31-bit smi range so it doesn't hit the
103402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // "unsafe smi" code that spills a register.
104402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    assertEquals(1073741824, 1 - a);
105402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
106402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    x = identity(-1073741824);
107402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    a = x + 1;
108402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    b = x + 1;
109402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    c = x + 1;
110402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    d = x + 1;
111402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    di = x + 1;
112402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    assertEquals(1073741824, 1 - b);
113402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
114402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    x = identity(-1073741824);
115402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    a = x + 1;
116402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    b = x + 1;
117402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    c = x + 1;
118402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    d = x + 1;
119402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    di = x + 1;
120402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    assertEquals(1073741824, 1 - c);
121402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
122402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    x = identity(-1073741824);
123402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    a = x + 1;
124402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    b = x + 1;
125402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    c = x + 1;
126402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    d = x + 1;
127402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    di = x + 1;
128402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    assertEquals(1073741824, 1 - d);
129402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
130402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    x = identity(-1073741824);
131402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    a = x + 1;
132402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    b = x + 1;
133402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    c = x + 1;
134402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    d = x + 1;
135402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    di = x + 1;
136402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    assertEquals(1073741824, 1 - di);
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    x = 3;
1396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    var w = { };
1406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    lookup(w, x);
1416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    lookup(w, x);
1426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    lookup(w, x);
1436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    x = 3;  // Terminate while loop.
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockcover_codegen_paths();
149