1/*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16declare interface ArkTools {
17    isAOTCompiled(args: any): boolean;
18}
19declare function print(arg:any):string;
20
21function printZero(x: any) {
22    if (Object.is(x, -0)) {
23        print("-0");
24    } else {
25        print(x);
26    }
27}
28function replace(a : number)
29{
30    return a;
31}
32
33// Use try to prevent inlining to main
34function printMax(x: any, y: any) {
35    try {
36        print(Math.max(x, y));
37    } finally {
38    }
39}
40
41function printMax1(x: any) {
42    try {
43        print(Math.max(x));
44    } finally {
45    }
46}
47
48function printMax3(x: any, y: any, z: any) {
49    try {
50        print(Math.max(x, y, z));
51    } finally {
52    }
53}
54
55let doubleObj = {
56    valueOf: () => { return 2.7; }
57}
58
59let nanObj = {
60    valueOf: () => { return "something"; }
61}
62
63let obj = {
64    valueOf: () => {
65        print("obj.valueOf")
66        return -23;
67    }
68};
69
70// Check without params
71//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
72print(Math.max()); //: -Infinity
73
74// Check with single param
75//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
76print(Math.max(0)); //: 0
77//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
78print(Math.max(567)); //: 567
79//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
80print(Math.max(-1e80)); //: -1e+80
81
82// Check with special float params
83//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
84print(Math.max(Infinity)); //: Infinity
85//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
86print(Math.max(-Infinity)); //: -Infinity
87//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
88print(Math.max(NaN)); //: NaN
89
90// Check with 2 int params
91//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
92print(Math.max(3, 300)); //: 300
93//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
94print(Math.max(300, 3)); //: 300
95//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
96print(Math.max(3, -2)); //: 3
97//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
98print(Math.max(-22, -2)); //: -2
99//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
100print(Math.max(-1, -1)); //: -1
101
102// Check with 2 float params
103//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
104print(Math.max(3.2, 300.7)); //: 300.7
105//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
106print(Math.max(300.7, 3.2)); //: 300.7
107//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
108print(Math.max(3e9, -2e10)); //: 3000000000
109//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
110print(Math.max(-22.1, -2e-10)); //: -2e-10
111//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
112print(Math.max(-1.8, -1.8)); //: -1.8
113//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
114print(Math.max(Infinity, -1.8)); //: Infinity
115//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
116print(Math.max(-1.8, Infinity)); //: Infinity
117//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
118print(Math.max(-Infinity, -1.8)); //: -1.8
119//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
120print(Math.max(-1.8, -Infinity)); //: -1.8
121//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
122print(Math.max(-1.8, NaN)); //: NaN
123//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
124print(Math.max(NaN, -1.8)); //: NaN
125//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
126print(Math.max(-Infinity, NaN)); //: NaN
127//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
128print(Math.max(Infinity, NaN)); //: NaN
129
130// Check 0 and -0
131//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
132//aot: [trace] aot inline function name: #*#printZero@builtinMathMax caller function name: func_main_0@builtinMathMax
133//aot: [trace] aot inline builtin: Object.is, caller function name:#*#printZero@builtinMathMax
134printZero(Math.max(0, -0));  //: 0
135//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
136//aot: [trace] aot inline function name: #*#printZero@builtinMathMax caller function name: func_main_0@builtinMathMax
137//aot: [trace] aot inline builtin: Object.is, caller function name:#*#printZero@builtinMathMax
138printZero(Math.max(-0, 0));  //: 0
139//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
140//aot: [trace] aot inline function name: #*#printZero@builtinMathMax caller function name: func_main_0@builtinMathMax
141//aot: [trace] aot inline builtin: Object.is, caller function name:#*#printZero@builtinMathMax
142printZero(Math.max(0, 0));   //: 0
143//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
144//aot: [trace] aot inline function name: #*#printZero@builtinMathMax caller function name: func_main_0@builtinMathMax
145//aot: [trace] aot inline builtin: Object.is, caller function name:#*#printZero@builtinMathMax
146printZero(Math.max(-0, -0)); //: -0
147//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
148//aot: [trace] aot inline function name: #*#printZero@builtinMathMax caller function name: func_main_0@builtinMathMax
149//aot: [trace] aot inline builtin: Object.is, caller function name:#*#printZero@builtinMathMax
150printZero(Math.max(-5, -0)); //: -0
151//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
152//aot: [trace] aot inline function name: #*#printZero@builtinMathMax caller function name: func_main_0@builtinMathMax
153//aot: [trace] aot inline builtin: Object.is, caller function name:#*#printZero@builtinMathMax
154printZero(Math.max(-5, 0)); //: 0
155
156// Check with int and float param
157//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
158print(Math.max(1.5, 3)); //: 3
159//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
160print(Math.max(3, 1.5)); //: 3
161//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
162print(Math.max(2.5, 1)); //: 2.5
163//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
164print(Math.max(1, 2.5)); //: 2.5
165//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
166print(Math.max(1, -Infinity)); //: 1
167//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
168print(Math.max(5, NaN)); //: NaN
169//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
170print(Math.max(NaN, 5)); //: NaN
171
172
173// Check with 3 params
174//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
175print(Math.max(2, 4, 6)); //: 6
176//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
177print(Math.max(4, 6, 2)); //: 6
178//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
179print(Math.max(6, 2, 4)); //: 6
180//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
181print(Math.max(-1, 1, 2.5)); //: 2.5
182
183// Check with 4 params
184//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
185print(Math.max(-4, 0, 2, -Infinity)); //: 2
186
187// Check with 5 params
188//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
189print(Math.max(1, 2, 1.5, 2, 8)); //: 8
190
191// Replace standard builtin
192let trueMax = Math.max
193Math.max = replace
194print(Math.max(-1.001, -90)); //: -1.001
195Math.max = trueMax
196
197//aot: [trace] aot inline builtin: Math.max, caller function name:#*#printMax@builtinMathMax
198printMax(-12, -100); //: -12
199// Call standard builtin with non-number param
200//aot: [trace] aot inline builtin: Math.max, caller function name:#*#printMax@builtinMathMax
201//aot: [trace] Check Type: NotNumber2
202printMax("abc", -100); //: NaN
203//aot: [trace] aot inline builtin: Math.max, caller function name:#*#printMax@builtinMathMax
204//aot: [trace] Check Type: NotNumber2
205printMax("-12", -100); //: -12
206
207if (ArkTools.isAOTCompiled(printMax)) {
208    // Replace standard builtin after call to standard builtin was profiled
209    Math.max = replace
210}
211//aot: [trace] Check Type: NotCallTarget1
212printMax(5, 12); //pgo: 12
213                  //aot: 5
214//aot: [trace] Check Type: NotCallTarget1
215printMax("abc", 2); //pgo: NaN
216                    //aot: abc
217Math.max = trueMax
218
219// Check IR correctness inside try-block
220try {
221    //aot: [trace] aot inline builtin: Math.max, caller function name:#*#printMax@builtinMathMax
222    printMax(19, 20); //: 20
223    //aot: [trace] aot inline builtin: Math.max, caller function name:#*#printMax@builtinMathMax
224    printMax(19, 12); //: 19
225    //aot: [trace] aot inline builtin: Math.max, caller function name:#*#printMax@builtinMathMax
226    //aot: [trace] Check Type: NotNumber2
227    printMax("abc", 5); //: NaN
228} catch (e) {
229}
230
231//aot: [trace] aot inline builtin: Math.max, caller function name:#*#printMax1@builtinMathMax
232//aot: [trace] Check Type: InconsistentType1
233//: obj.valueOf
234printMax1(obj); //: -23
235//aot: [trace] aot inline builtin: Math.max, caller function name:#*#printMax1@builtinMathMax
236//aot: [trace] Check Type: InconsistentType1
237printMax1(doubleObj); //: 2.7
238//aot: [trace] aot inline builtin: Math.max, caller function name:#*#printMax@builtinMathMax
239//aot: [trace] Check Type: NotNumber2
240printMax(doubleObj, doubleObj); //: 2.7
241//aot: [trace] aot inline builtin: Math.max, caller function name:#*#printMax@builtinMathMax
242//aot: [trace] Check Type: NotNumber2
243//: obj.valueOf
244printMax(nanObj, obj); //: NaN
245//aot: [trace] aot inline builtin: Math.max, caller function name:#*#printMax@builtinMathMax
246//aot: [trace] Check Type: NotNumber2
247//: obj.valueOf
248printMax(2, obj); //: 2
249//aot: [trace] aot inline builtin: Math.max, caller function name:#*#printMax@builtinMathMax
250//aot: [trace] Check Type: NotNumber2
251//: obj.valueOf
252printMax(-100, obj); //: -23
253
254// call obj.valueOf twice
255//aot: [trace] aot inline builtin: Math.max, caller function name:#*#printMax3@builtinMathMax
256//aot: [trace] Check Type: NotNumber2
257//: obj.valueOf
258//: obj.valueOf
259printMax3(NaN, obj, obj); //: NaN
260