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;
20function replace(a : number)
21{
22    return a;
23}
24
25function doAbs(x: any): number {
26    return Math.abs(x);
27}
28
29function printAbs(x: any) {
30    try {
31        print(doAbs(x));
32    } finally {
33    }
34}
35
36function printAbs2() {
37    try {
38        const INT_MAX: number = 2147483647;
39        const INT_MIN: number = -INT_MAX - 1;
40        print(Math.abs(INT_MIN));
41    } finally {
42    }
43}
44
45// Check without params
46//aot: [trace] aot inline builtin: Math.abs, caller function name:func_main_0@builtinMathAbs
47print(Math.abs()); //: NaN
48
49// Check with single int param
50//aot: [trace] aot inline builtin: Math.abs, caller function name:func_main_0@builtinMathAbs
51print(Math.abs(0)); //: 0
52//aot: [trace] aot inline builtin: Math.abs, caller function name:func_main_0@builtinMathAbs
53print(Math.abs(3)); //: 3
54//aot: [trace] aot inline builtin: Math.abs, caller function name:func_main_0@builtinMathAbs
55print(Math.abs(-5)); //: 5
56
57// Check with single float param
58//aot: [trace] aot inline builtin: Math.abs, caller function name:func_main_0@builtinMathAbs
59print(Math.abs(-1.5)); //: 1.5
60//aot: [trace] aot inline builtin: Math.abs, caller function name:func_main_0@builtinMathAbs
61print(Math.abs(Math.PI)); //: 3.141592653589793
62//aot: [trace] aot inline builtin: Math.abs, caller function name:func_main_0@builtinMathAbs
63print(Math.abs(-Math.PI)); //: 3.141592653589793
64//aot: [trace] aot inline builtin: Math.abs, caller function name:func_main_0@builtinMathAbs
65print(Math.abs(-1.9e80)); //: 1.9e+80
66//aot: [trace] aot inline builtin: Math.abs, caller function name:func_main_0@builtinMathAbs
67print(Math.abs(1.9e80)); //: 1.9e+80
68//aot: [trace] aot inline builtin: Math.abs, caller function name:func_main_0@builtinMathAbs
69print(Math.abs(-1.9e-80)); //: 1.9e-80
70//aot: [trace] aot inline builtin: Math.abs, caller function name:func_main_0@builtinMathAbs
71print(Math.abs(1.9e-80)); //: 1.9e-80
72
73
74// Check with special float params
75//aot: [trace] aot inline builtin: Math.abs, caller function name:func_main_0@builtinMathAbs
76print(Math.abs(Infinity)); //: Infinity
77//aot: [trace] aot inline builtin: Math.abs, caller function name:func_main_0@builtinMathAbs
78print(Math.abs(-Infinity)); //: Infinity
79//aot: [trace] aot inline builtin: Math.abs, caller function name:func_main_0@builtinMathAbs
80print(Math.abs(NaN)); //: NaN
81
82//aot: [trace] aot inline builtin: Math.abs, caller function name:func_main_0@builtinMathAbs
83print(1 / Math.abs(-0)); //: Infinity
84
85// Check with 2 params
86//aot: [trace] aot inline builtin: Math.abs, caller function name:func_main_0@builtinMathAbs
87print(Math.abs(3, 0)); //: 3
88
89// Check with 3 params
90//aot: [trace] aot inline builtin: Math.abs, caller function name:func_main_0@builtinMathAbs
91print(Math.abs(-3, 0, 0)); //: 3
92
93// Check with 4 params
94//aot: [trace] aot inline builtin: Math.abs, caller function name:func_main_0@builtinMathAbs
95print(Math.abs(4, 0, 0, 0)); //: 4
96
97// Check with 5 params
98//aot: [trace] aot inline builtin: Math.abs, caller function name:func_main_0@builtinMathAbs
99print(Math.abs(-4, 0, 0, 0, 0)); //: 4
100
101// Replace standard builtin
102let true_abs = Math.abs
103Math.abs = replace
104
105// no deopt
106print(Math.abs(-1.001)); //: -1.001
107Math.abs = true_abs
108
109// Check edge cases
110const INT_MAX: number = 2147483647;
111const INT_MIN: number = -INT_MAX - 1;
112//aot: [trace] aot inline builtin: Math.abs, caller function name:#*#doAbs@builtinMathAbs
113printAbs(INT_MAX); //: 2147483647
114//aot: [trace] aot inline builtin: Math.abs, caller function name:#*#doAbs@builtinMathAbs
115printAbs(2147483648); //: 2147483648
116//aot: [trace] aot inline builtin: Math.abs, caller function name:#*#doAbs@builtinMathAbs
117printAbs(-INT_MAX); //: 2147483647
118//aot: [trace] aot inline builtin: Math.abs, caller function name:#*#printAbs2@builtinMathAbs
119//aot: [trace] Check Type: NotInt3
120printAbs2(); //: 2147483648
121//aot: [trace] aot inline builtin: Math.abs, caller function name:#*#doAbs@builtinMathAbs
122printAbs(INT_MIN - 1); //: 2147483649
123
124//aot: [trace] aot inline builtin: Math.abs, caller function name:#*#doAbs@builtinMathAbs
125printAbs(-12); //: 12
126// Call standard builtin with non-number param
127//aot: [trace] aot inline builtin: Math.abs, caller function name:#*#doAbs@builtinMathAbs
128//aot: [trace] Check Type: NotNumber2
129printAbs("abc"); //: NaN
130//aot: [trace] aot inline builtin: Math.abs, caller function name:#*#doAbs@builtinMathAbs
131//aot: [trace] Check Type: NotNumber2
132printAbs("-12"); //: 12
133
134if (ArkTools.isAOTCompiled(printAbs)) {
135    // Replace standard builtin after call to standard builtin was profiled
136    Math.abs = replace
137}
138printAbs(-12); //pgo: 12
139//aot: [trace] Check Type: NotCallTarget1
140//aot: -12
141
142printAbs("abc"); //pgo: NaN
143//aot: [trace] Check Type: NotCallTarget1
144//aot: abc
145
146Math.abs = true_abs
147
148// Check IR correctness inside try-block
149try {
150    //aot: [trace] aot inline builtin: Math.abs, caller function name:#*#doAbs@builtinMathAbs
151    printAbs(-12); //: 12
152    //aot: [trace] aot inline builtin: Math.abs, caller function name:#*#doAbs@builtinMathAbs
153    //aot: [trace] Check Type: NotNumber2
154    printAbs("abc"); //: NaN
155} catch (e) {
156}
157
158let obj = {
159    valueOf: () => { return -23; }
160};
161//aot: [trace] aot inline builtin: Math.abs, caller function name:func_main_0@builtinMathAbs
162//aot: [trace] Check Type: NotNumber2
163print(Math.abs(obj)); //: 23
164
165function Throwing() {
166    this.value = -14;
167}
168Throwing.prototype.valueOf = function() {
169    if (this.value > 0) {
170        throw new Error("already positive");
171    }
172    return this.value;
173}
174let throwingObj = new Throwing();
175
176try {
177    print(Math.abs(throwingObj)); //: 14
178    throwingObj.value = 10;
179    print(Math.abs(throwingObj)); //: Error: already positive
180} catch(e) {
181    print(e);
182} finally {
183    print(Math.abs(obj)); //: 23
184}