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 doGet(x: any): any {
26    return myMap.get(x);
27}
28
29function printGet(x: any) {
30    try {
31        print(doGet(x));
32    } finally {
33    }
34}
35
36function printGet2(x: any, y: any) {
37    try {
38        print(x.get(y));
39    } finally {
40    }
41}
42
43let myMap = new Map([[0, 0], [0.0, 5], [-1, 1], [2.5, -2.5], [NaN, Infinity], [2000, -0.0], [56, "oops"], ["xyz", "12345"], [-3, 1]]);
44
45// Check without params
46//aot: [trace] aot inline builtin: Map.get, caller function name:func_main_0@builtinMapGet
47print(myMap.get()); //: undefined
48
49// Check with adding element undefined
50myMap.set(undefined, 42);
51//aot: [trace] aot inline builtin: Map.get, caller function name:func_main_0@builtinMapGet
52print(myMap.get()); //: 42
53
54// Check with single param
55//aot: [trace] aot inline builtin: Map.get, caller function name:func_main_0@builtinMapGet
56print(myMap.get(0)); //: 5
57//aot: [trace] aot inline builtin: Map.get, caller function name:func_main_0@builtinMapGet
58print(myMap.get(3)); //: undefined
59//aot: [trace] aot inline builtin: Map.get, caller function name:func_main_0@builtinMapGet
60print(myMap.get(2.5)); //: -2.5
61//aot: [trace] aot inline builtin: Map.get, caller function name:func_main_0@builtinMapGet
62print(myMap.get(NaN)); //: Infinity
63//aot: [trace] aot inline builtin: Map.get, caller function name:func_main_0@builtinMapGet
64print("1/x: " + 1 / myMap.get(2000)); //: 1/x: -Infinity
65
66// Check with 2 params
67//aot: [trace] aot inline builtin: Map.get, caller function name:func_main_0@builtinMapGet
68print(myMap.get(0, 0)); //: 5
69
70// Check with 3 params
71//aot: [trace] aot inline builtin: Map.get, caller function name:func_main_0@builtinMapGet
72print(myMap.get(-1, 10.2, 15)); //: 1
73
74// Check with 4 params
75//aot: [trace] aot inline builtin: Map.get, caller function name:func_main_0@builtinMapGet
76print(myMap.get(2.5, -800, 0.56, 0)); //: -2.5
77
78// Check after inserting elements
79myMap.set(2000, 1e-98);
80myMap.set(133.33, -1);
81//aot: [trace] aot inline builtin: Map.get, caller function name:func_main_0@builtinMapGet
82print(myMap.get(2000)); //: 1e-98
83//aot: [trace] aot inline builtin: Map.get, caller function name:func_main_0@builtinMapGet
84print(myMap.get(133.33)); //: -1
85
86// Replace standard builtin
87let true_get = myMap.get
88myMap.get = replace
89
90// no deopt
91print(myMap.get(2.5)); //: 2.5
92myMap.get = true_get
93
94//aot: [trace] aot inline builtin: Map.get, caller function name:#*#doGet@builtinMapGet
95printGet(-1); //: 1
96// Call standard builtin with non-number param
97//aot: [trace] aot inline builtin: Map.get, caller function name:func_main_0@builtinMapGet
98print(myMap.get("abc")); //: undefined
99//aot: [trace] aot inline builtin: Map.get, caller function name:func_main_0@builtinMapGet
100print(myMap.get("-1")); //: undefined
101//aot: [trace] aot inline builtin: Map.get, caller function name:func_main_0@builtinMapGet
102print(myMap.get(56)); //: oops
103//aot: [trace] aot inline builtin: Map.get, caller function name:func_main_0@builtinMapGet
104print(myMap.get("xyz")); //: 12345
105
106if (ArkTools.isAOTCompiled(printGet)) {
107    // Replace standard builtin after call to standard builtin was profiled
108    myMap.get = replace
109}
110printGet(2.5); //pgo: -2.5
111//aot: [trace] Check Type: NotCallTarget1
112//aot: 2.5
113
114printGet("abc"); //pgo: undefined
115//aot: [trace] Check Type: NotCallTarget1
116//aot: abc
117
118myMap.get = true_get
119
120// Check IR correctness inside try-block
121try {
122    //aot: [trace] aot inline builtin: Map.get, caller function name:#*#doGet@builtinMapGet
123    printGet(2.5); //: -2.5
124    //aot: [trace] aot inline builtin: Map.get, caller function name:#*#doGet@builtinMapGet
125    printGet("abc"); //: undefined
126} catch (e) {
127}
128
129let obj = {};
130obj.valueOf = (() => { return 0; })
131//aot: [trace] aot inline builtin: Map.get, caller function name:func_main_0@builtinMapGet
132print(myMap.get(obj)); //: undefined
133
134function Throwing() {
135    this.value = 2;
136    Throwing.prototype.valueOf = function() {
137        if (this.value > 0) {
138            throw new Error("positive");
139        }
140        return this.value;
141    }
142}
143let throwingObj = new Throwing();
144try {
145    //aot: [trace] aot inline builtin: Map.get, caller function name:func_main_0@builtinMapGet
146    print(myMap.get(throwingObj)); //: undefined
147} catch(e) {
148    print(e);
149} finally {
150    //aot: [trace] aot inline builtin: Map.get, caller function name:func_main_0@builtinMapGet
151    print(myMap.get(obj)); //: undefined
152}
153
154// Check after clearing
155myMap.clear();
156//aot: [trace] aot inline builtin: Map.clear, caller function name:func_main_0@builtinMapGet
157print(myMap.get(2000));
158//aot: [trace] aot inline builtin: Map.get, caller function name:func_main_0@builtinMapGet
159//: undefined
160
161let trueGet = Map.prototype.get
162let m = new Map()
163m.set(1, 2)
164m.set(2, 4)
165m.set("ab", 5)
166m.set("cd", "e")
167let obj1 = {}
168m.set(obj1, "obj")
169
170//aot: [trace] aot inline builtin: Map.get, caller function name:func_main_0@builtinMapGet
171print(m.get(1)) //: 2
172//aot: [trace] aot inline builtin: Map.get, caller function name:func_main_0@builtinMapGet
173print(m.get(2)) //: 4
174//aot: [trace] aot inline builtin: Map.get, caller function name:func_main_0@builtinMapGet
175print(m.get(3)) //: undefined
176//aot: [trace] aot inline builtin: Map.get, caller function name:func_main_0@builtinMapGet
177print(m.get("ab")) //: 5
178//aot: [trace] aot inline builtin: Map.get, caller function name:func_main_0@builtinMapGet
179print(m.get("cd")) //: e
180//aot: [trace] aot inline builtin: Map.get, caller function name:func_main_0@builtinMapGet
181print(m.get("x")) //: undefined
182//aot: [trace] aot inline builtin: Map.get, caller function name:func_main_0@builtinMapGet
183print(m.get(obj1)) //: obj
184let obj2 = {}
185//aot: [trace] aot inline builtin: Map.get, caller function name:func_main_0@builtinMapGet
186print(m.get(obj2)) //: undefined
187//aot: [trace] aot inline builtin: Map.get, caller function name:func_main_0@builtinMapGet
188print(m.get()) //: undefined
189m.set(undefined, -1)
190//aot: [trace] aot inline builtin: Map.get, caller function name:func_main_0@builtinMapGet
191print(m.get()) //: -1
192
193function checkObjWithMapProto() {
194    let o = {};
195    Object.setPrototypeOf(o, Map.prototype);
196    try {
197        print((o as Map<number, number>).get(1));
198    } catch(e) {
199        print(e);
200    }
201}
202
203//aot: [trace] Check Type: NotCallTarget1
204//: TypeError: obj is not JSMap
205checkObjWithMapProto();
206
207let notMap = {
208    get(x: any) {
209        return this[x] + x
210    }
211}
212
213print("baseline") //: baseline
214m[10] = 20
215let m2 = new Map([[1, 2]])
216let m3 = new Map([[1, 2]])
217let m4 = new Map([[1, 2]])
218//aot: [trace] aot inline builtin: Map.get, caller function name:#*#printGet2@builtinMapGet
219printGet2(m, 10) //: undefined
220//aot: [trace] aot inline builtin: Map.get, caller function name:#*#printGet2@builtinMapGet
221printGet2(m2, 1) //: 2
222//aot: [trace] aot inline builtin: Map.get, caller function name:#*#printGet2@builtinMapGet
223printGet2(m3, 1) //: 2
224//aot: [trace] aot inline builtin: Map.get, caller function name:#*#printGet2@builtinMapGet
225printGet2(m4, 1) //: 2
226
227print("case 0") //: case 0
228if (ArkTools.isAOTCompiled(printGet2)) {
229    m4.garbage = function(x: any) {
230        return undefined
231    }
232}
233// Nothing changed
234//aot: [trace] aot inline builtin: Map.get, caller function name:#*#printGet2@builtinMapGet
235printGet2(m, 10) //: undefined
236//aot: [trace] aot inline builtin: Map.get, caller function name:#*#printGet2@builtinMapGet
237printGet2(m2, 1) //: 2
238//aot: [trace] aot inline builtin: Map.get, caller function name:#*#printGet2@builtinMapGet
239printGet2(m3, 1) //: 2
240printGet2(m4, 1) //aot: [trace] Check Type: BuiltinInstanceHClassMismatch
241                //: 2
242
243print("case 1") //: case 1
244if (ArkTools.isAOTCompiled(printGet2)) {
245    m3.get = function(x: any) {
246        return -x
247    }
248}
249
250//aot: [trace] aot inline builtin: Object.getPrototypeOf, caller function name:func_main_0@builtinMapGet
251print(Object.getPrototypeOf(m3) === Map.prototype) //: true
252
253//aot: [trace] aot inline builtin: Map.get, caller function name:#*#printGet2@builtinMapGet
254printGet2(m, 10) //: undefined
255//aot: [trace] aot inline builtin: Map.get, caller function name:#*#printGet2@builtinMapGet
256printGet2(m2, 1) //: 2
257printGet2(m3, 1) //pgo: 2
258                //aot: [trace] Check Type: BuiltinInstanceHClassMismatch
259                //aot: -1
260
261print("case 2") //: case 2
262let mimicMap = {
263    get: trueGet
264}
265let mm = new Map([[1, 2]])
266//aot: [trace] aot inline builtin: Map.get, caller function name:#*#printGet2@builtinMapGet
267printGet2(mm, 1) //: 2
268if (ArkTools.isAOTCompiled(printGet2)) {
269    Object.setPrototypeOf(mm, mimicMap)
270}
271printGet2(mm, 1) //aot: [trace] Check Type: BuiltinInstanceHClassMismatch
272                 //: 2
273
274print("case 3") //: case 3
275if (ArkTools.isAOTCompiled(printGet2)) {
276    Map.prototype.get = function(x: any) {
277        return -x * 10
278    }
279}
280
281printGet2(m, 10) //pgo: undefined
282                //aot: [trace] Check Type: NotCallTarget1
283                //aot: -100
284printGet2(m2, 1) //pgo: 2
285                //aot: [trace] Check Type: NotCallTarget1
286                //aot: -10
287printGet2(m3, 1) //pgo: 2
288                //aot: [trace] Check Type: BuiltinInstanceHClassMismatch
289                //aot: -1
290
291print("case 4") //: case 4
292if (ArkTools.isAOTCompiled(printGet2)) {
293    Object.setPrototypeOf(m, notMap)
294}
295
296printGet2(m, 10) //pgo: undefined
297                //aot: [trace] Check Type: BuiltinInstanceHClassMismatch
298                //aot: 30
299printGet2(m2, 1) //pgo: 2
300                //aot: [trace] Check Type: NotCallTarget1
301                //aot: -10
302printGet2(m3, 1) //pgo: 2
303                //aot: [trace] Check Type: BuiltinInstanceHClassMismatch
304                //aot: -1
305