1// Copyright 2013 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
29
30// general tests
31var e31 = Math.pow(2, 31);
32
33assertEquals(-e31, -1*e31);
34assertEquals(e31, -1*e31*(-1));
35assertEquals(e31, -1*-e31);
36assertEquals(e31, -e31*(-1));
37
38var x = {toString : function() {return 1}}
39function add(a,b){return a+b;}
40add(1,x);
41add(1,x);
42%OptimizeFunctionOnNextCall(add);
43add(1,x);
44x.toString = function() {return "2"};
45
46assertEquals(add(1,x), "12");
47
48// Test the correct placement of the simulates in TruncateToNumber:
49function Checker() {
50  this.str = "1";
51  var toStringCalled = 0;
52  var toStringExpected = 0;
53  this.toString = function() {
54    toStringCalled++;
55    return this.str;
56  };
57  this.check = function() {
58    toStringExpected++;
59    assertEquals(toStringExpected, toStringCalled);
60  };
61};
62var left = new Checker();
63var right = new Checker();
64
65function test(fun,check_fun,a,b,does_throw) {
66  left.str = a;
67  right.str = b;
68  try {
69    assertEquals(check_fun(a,b), fun(left, right));
70    assertTrue(!does_throw);
71  } catch(e) {
72    if (e instanceof TypeError) {
73      assertTrue(!!does_throw);
74    } else {
75      throw e;
76    }
77  } finally {
78    left.check();
79    if (!does_throw || does_throw>1) {
80      right.check();
81    }
82  }
83}
84
85function minus(a,b) { return a-b };
86function check_minus(a,b) { return a-b };
87function mod(a,b) { return a%b };
88function check_mod(a,b) { return a%b };
89
90test(minus,check_minus,1,2);
91// Bailout on left
92test(minus,check_minus,1<<30,1);
93// Bailout on right
94test(minus,check_minus,1,1<<30);
95// Bailout on result
96test(minus,check_minus,1<<30,-(1<<30));
97
98// Some more interesting things
99test(minus,check_minus,1,1.4);
100test(minus,check_minus,1.3,4);
101test(minus,check_minus,1.3,1.4);
102test(minus,check_minus,1,2);
103test(minus,check_minus,1,undefined);
104test(minus,check_minus,1,2);
105test(minus,check_minus,1,true);
106test(minus,check_minus,1,2);
107test(minus,check_minus,1,null);
108test(minus,check_minus,1,2);
109test(minus,check_minus,1,"");
110test(minus,check_minus,1,2);
111
112// Throw on left
113test(minus,check_minus,{},1,1);
114// Throw on right
115test(minus,check_minus,1,{},2);
116// Throw both
117test(minus,check_minus,{},{},1);
118
119test(minus,check_minus,1,2);
120
121// Now with optimized code
122test(mod,check_mod,1,2);
123%OptimizeFunctionOnNextCall(mod);
124test(mod,check_mod,1,2);
125
126test(mod,check_mod,1<<30,1);
127%OptimizeFunctionOnNextCall(mod);
128test(mod,check_mod,1<<30,1);
129test(mod,check_mod,1,1<<30);
130%OptimizeFunctionOnNextCall(mod);
131test(mod,check_mod,1,1<<30);
132test(mod,check_mod,1<<30,-(1<<30));
133%OptimizeFunctionOnNextCall(mod);
134test(mod,check_mod,1<<30,-(1<<30));
135
136test(mod,check_mod,1,{},2);
137%OptimizeFunctionOnNextCall(mod);
138test(mod,check_mod,1,{},2);
139
140test(mod,check_mod,1,2);
141
142
143// test oddballs
144function t1(a, b) {return a-b}
145assertEquals(t1(1,2), 1-2);
146assertEquals(t1(2,true), 2-1);
147assertEquals(t1(false,2), 0-2);
148assertEquals(t1(1,2.4), 1-2.4);
149assertEquals(t1(1.3,2.4), 1.3-2.4);
150assertEquals(t1(true,2.4), 1-2.4);
151assertEquals(t1(1,undefined), 1-NaN);
152assertEquals(t1(1,1<<30), 1-(1<<30));
153assertEquals(t1(1,2), 1-2);
154
155function t2(a, b) {return a/b}
156assertEquals(t2(1,2), 1/2);
157assertEquals(t2(null,2), 0/2);
158assertEquals(t2(null,-2), 0/-2);
159assertEquals(t2(2,null), 2/0);
160assertEquals(t2(-2,null), -2/0);
161assertEquals(t2(1,2.4), 1/2.4);
162assertEquals(t2(1.3,2.4), 1.3/2.4);
163assertEquals(t2(null,2.4), 0/2.4);
164assertEquals(t2(1.3,null), 1.3/0);
165assertEquals(t2(undefined,2), NaN/2);
166assertEquals(t2(1,1<<30), 1/(1<<30));
167assertEquals(t2(1,2), 1/2);
168
169
170// Assert that the hole is not truncated to nan for string add.
171function string_add(a,i) {
172  var d = [0.1, ,0.3];
173  return a + d[i];
174}
175
176string_add(1.1, 0);
177string_add("", 0);
178%OptimizeFunctionOnNextCall(string_add);
179string_add(1.1, 0);
180// There comes the hole
181assertEquals("undefined", string_add("", 1));
182